diff --git a/.gitignore b/.gitignore index 852b692f99b50..9145a9fa67b06 100644 --- a/.gitignore +++ b/.gitignore @@ -25,4 +25,3 @@ NashornProfile.txt **/core.[0-9]* *.rej *.orig -test/benchmarks/**/target diff --git a/doc/testing.html b/doc/testing.html index b9838735e4f6e..89a9b1b23b75f 100644 --- a/doc/testing.html +++ b/doc/testing.html @@ -450,7 +450,7 @@

TIMEOUT_FACTOR

programmatically wait a certain amount of time will apply this factor. If we run in forced compilation mode (-Xcomp), the build system will automatically adjust this factor to compensate for less -performance. Defaults to 4.

+performance. Defaults to 1.

FAILURE_HANDLER_TIMEOUT

Sets the argument -timeoutHandlerTimeout for JTReg. The default value is 0. This is only valid if the failure handler is diff --git a/doc/testing.md b/doc/testing.md index 0144610a5bf92..324f9645c270c 100644 --- a/doc/testing.md +++ b/doc/testing.md @@ -387,7 +387,7 @@ The `TIMEOUT_FACTOR` is forwarded to JTReg framework itself (`-timeoutFactor`). Also, some test cases that programmatically wait a certain amount of time will apply this factor. If we run in forced compilation mode (`-Xcomp`), the build system will automatically -adjust this factor to compensate for less performance. Defaults to 4. +adjust this factor to compensate for less performance. Defaults to 1. #### FAILURE_HANDLER_TIMEOUT diff --git a/make/RunTests.gmk b/make/RunTests.gmk index 947389f64f99c..7b05a0ba12fdb 100644 --- a/make/RunTests.gmk +++ b/make/RunTests.gmk @@ -946,8 +946,8 @@ define SetupRunJtregTestBody JTREG_ALL_OPTIONS := $$(JTREG_JAVA_OPTIONS) $$(JTREG_VM_OPTIONS) JTREG_AUTO_PROBLEM_LISTS := - # Please reach consensus before changing this. - JTREG_AUTO_TIMEOUT_FACTOR := 4 + # Please reach consensus before changing this. It was not easy changing it to a `1`. + JTREG_AUTO_TIMEOUT_FACTOR := 1 ifneq ($$(findstring -Xcomp, $$(JTREG_ALL_OPTIONS)), ) JTREG_AUTO_PROBLEM_LISTS += ProblemList-Xcomp.txt diff --git a/make/conf/github-actions.conf b/make/conf/github-actions.conf index bd73e909062dd..74a830cbcc289 100644 --- a/make/conf/github-actions.conf +++ b/make/conf/github-actions.conf @@ -29,21 +29,21 @@ GTEST_VERSION=1.14.0 JTREG_VERSION=8.1+1 LINUX_X64_BOOT_JDK_EXT=tar.gz -LINUX_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk25/bd75d5f9689641da8e1daabeccb5528b/36/GPL/openjdk-25_linux-x64_bin.tar.gz -LINUX_X64_BOOT_JDK_SHA256=59cdcaf255add4721de38eb411d4ecfe779356b61fb671aee63c7dec78054c2b +LINUX_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk24/1f9ff9062db4449d8ca828c504ffae90/36/GPL/openjdk-24_linux-x64_bin.tar.gz +LINUX_X64_BOOT_JDK_SHA256=88b090fa80c6c1d084ec9a755233967458788e2c0777ae2e172230c5c692d7ef ALPINE_LINUX_X64_BOOT_JDK_EXT=tar.gz -ALPINE_LINUX_X64_BOOT_JDK_URL=https://github.com/adoptium/temurin25-binaries/releases/download/jdk-25%2B36/OpenJDK25U-jdk_x64_alpine-linux_hotspot_25_36.tar.gz -ALPINE_LINUX_X64_BOOT_JDK_SHA256=637e47474d411ed86134f413af7d5fef4180ddb0bf556347b7e74a88cf8904c8 +ALPINE_LINUX_X64_BOOT_JDK_URL=https://github.com/adoptium/temurin24-binaries/releases/download/jdk-24%2B36/OpenJDK24U-jdk_x64_alpine-linux_hotspot_24_36.tar.gz +ALPINE_LINUX_X64_BOOT_JDK_SHA256=a642608f0da78344ee6812fb1490b8bc1d7ad5a18064c70994d6f330568c51cb MACOS_AARCH64_BOOT_JDK_EXT=tar.gz -MACOS_AARCH64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk25/bd75d5f9689641da8e1daabeccb5528b/36/GPL/openjdk-25_macos-aarch64_bin.tar.gz -MACOS_AARCH64_BOOT_JDK_SHA256=2006337bf326fdfdf6117081751ba38c1c8706d63419ecac7ff102ff7c776876 +MACOS_AARCH64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk24/1f9ff9062db4449d8ca828c504ffae90/36/GPL/openjdk-24_macos-aarch64_bin.tar.gz +MACOS_AARCH64_BOOT_JDK_SHA256=f7133238a12714a62c5ad2bd4da6741130be1a82512065da9ca23dee26b2d3d3 MACOS_X64_BOOT_JDK_EXT=tar.gz -MACOS_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk25/bd75d5f9689641da8e1daabeccb5528b/36/GPL/openjdk-25_macos-x64_bin.tar.gz -MACOS_X64_BOOT_JDK_SHA256=47482ad9888991ecac9b2bcc131e2b53ff78aff275104cef85f66252308e8a09 +MACOS_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk24/1f9ff9062db4449d8ca828c504ffae90/36/GPL/openjdk-24_macos-x64_bin.tar.gz +MACOS_X64_BOOT_JDK_SHA256=6bbfb1d01741cbe55ab90299cb91464b695de9a3ace85c15131aa2f50292f321 WINDOWS_X64_BOOT_JDK_EXT=zip -WINDOWS_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk25/bd75d5f9689641da8e1daabeccb5528b/36/GPL/openjdk-25_windows-x64_bin.zip -WINDOWS_X64_BOOT_JDK_SHA256=85bcc178461e2cb3c549ab9ca9dfa73afd54c09a175d6510d0884071867137d3 +WINDOWS_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk24/1f9ff9062db4449d8ca828c504ffae90/36/GPL/openjdk-24_windows-x64_bin.zip +WINDOWS_X64_BOOT_JDK_SHA256=11d1d9f6ac272d5361c8a0bef01894364081c7fb1a6914c2ad2fc312ae83d63b diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js index 795335d7c3cf9..9706321d7b60c 100644 --- a/make/conf/jib-profiles.js +++ b/make/conf/jib-profiles.js @@ -387,8 +387,8 @@ var getJibProfilesCommon = function (input, data) { }; }; - common.boot_jdk_version = "25"; - common.boot_jdk_build_number = "37"; + common.boot_jdk_version = "24"; + common.boot_jdk_build_number = "36"; common.boot_jdk_home = input.get("boot_jdk", "install_path") + "/jdk-" + common.boot_jdk_version + (input.build_os == "macosx" ? ".jdk/Contents/Home" : ""); diff --git a/make/conf/version-numbers.conf b/make/conf/version-numbers.conf index 977809535ba6a..38d6e42dff91b 100644 --- a/make/conf/version-numbers.conf +++ b/make/conf/version-numbers.conf @@ -37,6 +37,6 @@ DEFAULT_VERSION_DATE=2026-03-17 DEFAULT_VERSION_CLASSFILE_MAJOR=70 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`" DEFAULT_VERSION_CLASSFILE_MINOR=0 DEFAULT_VERSION_DOCS_API_SINCE=11 -DEFAULT_ACCEPTABLE_BOOT_VERSIONS="25 26" +DEFAULT_ACCEPTABLE_BOOT_VERSIONS="24 25 26" DEFAULT_JDK_SOURCE_TARGET_VERSION=26 DEFAULT_PROMOTED_VERSION_PRE=ea diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index 5734519301e28..51cdf8c71dfe2 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -1266,39 +1266,39 @@ source %{ // adlc register classes to make AArch64 rheapbase (r27) and rfp (r29) // registers conditionally reserved. - _ANY_REG32_mask.assignFrom(_ALL_REG32_mask); - _ANY_REG32_mask.remove(OptoReg::as_OptoReg(r31_sp->as_VMReg())); + _ANY_REG32_mask = _ALL_REG32_mask; + _ANY_REG32_mask.Remove(OptoReg::as_OptoReg(r31_sp->as_VMReg())); - _ANY_REG_mask.assignFrom(_ALL_REG_mask); + _ANY_REG_mask = _ALL_REG_mask; - _PTR_REG_mask.assignFrom(_ALL_REG_mask); + _PTR_REG_mask = _ALL_REG_mask; - _NO_SPECIAL_REG32_mask.assignFrom(_ALL_REG32_mask); - _NO_SPECIAL_REG32_mask.subtract(_NON_ALLOCATABLE_REG32_mask); + _NO_SPECIAL_REG32_mask = _ALL_REG32_mask; + _NO_SPECIAL_REG32_mask.SUBTRACT(_NON_ALLOCATABLE_REG32_mask); - _NO_SPECIAL_REG_mask.assignFrom(_ALL_REG_mask); - _NO_SPECIAL_REG_mask.subtract(_NON_ALLOCATABLE_REG_mask); + _NO_SPECIAL_REG_mask = _ALL_REG_mask; + _NO_SPECIAL_REG_mask.SUBTRACT(_NON_ALLOCATABLE_REG_mask); - _NO_SPECIAL_PTR_REG_mask.assignFrom(_ALL_REG_mask); - _NO_SPECIAL_PTR_REG_mask.subtract(_NON_ALLOCATABLE_REG_mask); + _NO_SPECIAL_PTR_REG_mask = _ALL_REG_mask; + _NO_SPECIAL_PTR_REG_mask.SUBTRACT(_NON_ALLOCATABLE_REG_mask); // r27 is not allocatable when compressed oops is on and heapbase is not // zero, compressed klass pointers doesn't use r27 after JDK-8234794 if (UseCompressedOops && (CompressedOops::base() != nullptr)) { - _NO_SPECIAL_REG32_mask.remove(OptoReg::as_OptoReg(r27->as_VMReg())); - _NO_SPECIAL_REG_mask.remove(OptoReg::as_OptoReg(r27->as_VMReg())); - _NO_SPECIAL_PTR_REG_mask.remove(OptoReg::as_OptoReg(r27->as_VMReg())); + _NO_SPECIAL_REG32_mask.Remove(OptoReg::as_OptoReg(r27->as_VMReg())); + _NO_SPECIAL_REG_mask.Remove(OptoReg::as_OptoReg(r27->as_VMReg())); + _NO_SPECIAL_PTR_REG_mask.Remove(OptoReg::as_OptoReg(r27->as_VMReg())); } // r29 is not allocatable when PreserveFramePointer is on if (PreserveFramePointer) { - _NO_SPECIAL_REG32_mask.remove(OptoReg::as_OptoReg(r29->as_VMReg())); - _NO_SPECIAL_REG_mask.remove(OptoReg::as_OptoReg(r29->as_VMReg())); - _NO_SPECIAL_PTR_REG_mask.remove(OptoReg::as_OptoReg(r29->as_VMReg())); + _NO_SPECIAL_REG32_mask.Remove(OptoReg::as_OptoReg(r29->as_VMReg())); + _NO_SPECIAL_REG_mask.Remove(OptoReg::as_OptoReg(r29->as_VMReg())); + _NO_SPECIAL_PTR_REG_mask.Remove(OptoReg::as_OptoReg(r29->as_VMReg())); } - _NO_SPECIAL_NO_RFP_PTR_REG_mask.assignFrom(_NO_SPECIAL_PTR_REG_mask); - _NO_SPECIAL_NO_RFP_PTR_REG_mask.remove(OptoReg::as_OptoReg(r29->as_VMReg())); + _NO_SPECIAL_NO_RFP_PTR_REG_mask = _NO_SPECIAL_PTR_REG_mask; + _NO_SPECIAL_NO_RFP_PTR_REG_mask.Remove(OptoReg::as_OptoReg(r29->as_VMReg())); } // Optimizaton of volatile gets and puts @@ -1734,7 +1734,7 @@ uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const { } //============================================================================= -const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::EMPTY; +const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::Empty; int ConstantTable::calculate_table_base_offset() const { return 0; // absolute addressing, no offset @@ -2520,10 +2520,10 @@ uint Matcher::int_pressure_limit() // as a spilled LRG. Spilling heuristics(Spill-USE) explicitly skip // derived pointers and lastly fail to spill after reaching maximum // number of iterations. Lowering the default pressure threshold to - // (_NO_SPECIAL_REG32_mask.size() minus 1) forces CallNode to become + // (_NO_SPECIAL_REG32_mask.Size() minus 1) forces CallNode to become // a high register pressure area of the code so that split_DEF can // generate DefinitionSpillCopy for the derived pointer. - uint default_int_pressure_threshold = _NO_SPECIAL_REG32_mask.size() - 1; + uint default_int_pressure_threshold = _NO_SPECIAL_REG32_mask.Size() - 1; if (!PreserveFramePointer) { // When PreserveFramePointer is off, frame pointer is allocatable, // but different from other SOC registers, it is excluded from @@ -2538,34 +2538,34 @@ uint Matcher::int_pressure_limit() uint Matcher::float_pressure_limit() { // _FLOAT_REG_mask is generated by adlc from the float_reg register class. - return (FLOATPRESSURE == -1) ? _FLOAT_REG_mask.size() : FLOATPRESSURE; + return (FLOATPRESSURE == -1) ? _FLOAT_REG_mask.Size() : FLOATPRESSURE; } bool Matcher::use_asm_for_ldiv_by_con(jlong divisor) { return false; } -const RegMask& Matcher::divI_proj_mask() { +RegMask Matcher::divI_proj_mask() { ShouldNotReachHere(); - return RegMask::EMPTY; + return RegMask(); } // Register for MODI projection of divmodI. -const RegMask& Matcher::modI_proj_mask() { +RegMask Matcher::modI_proj_mask() { ShouldNotReachHere(); - return RegMask::EMPTY; + return RegMask(); } // Register for DIVL projection of divmodL. -const RegMask& Matcher::divL_proj_mask() { +RegMask Matcher::divL_proj_mask() { ShouldNotReachHere(); - return RegMask::EMPTY; + return RegMask(); } // Register for MODL projection of divmodL. -const RegMask& Matcher::modL_proj_mask() { +RegMask Matcher::modL_proj_mask() { ShouldNotReachHere(); - return RegMask::EMPTY; + return RegMask(); } bool size_fits_all_mem_uses(AddPNode* addp, int shift) { diff --git a/src/hotspot/cpu/aarch64/aarch64_vector.ad b/src/hotspot/cpu/aarch64/aarch64_vector.ad index 3379041b2ccac..ef35b66003d1b 100644 --- a/src/hotspot/cpu/aarch64/aarch64_vector.ad +++ b/src/hotspot/cpu/aarch64/aarch64_vector.ad @@ -7081,31 +7081,29 @@ instruct vcompress(vReg dst, vReg src, pRegGov pg) %{ %} instruct vcompressB(vReg dst, vReg src, pReg pg, vReg tmp1, vReg tmp2, - vReg tmp3, pReg ptmp, pRegGov pgtmp) %{ + vReg tmp3, vReg tmp4, pReg ptmp, pRegGov pgtmp) %{ predicate(UseSVE > 0 && Matcher::vector_element_basic_type(n) == T_BYTE); - effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP ptmp, TEMP pgtmp); + effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP ptmp, TEMP pgtmp); match(Set dst (CompressV src pg)); - format %{ "vcompressB $dst, $src, $pg\t# KILL $tmp1, $tmp2, $tmp3, $ptmp, $pgtmp" %} + format %{ "vcompressB $dst, $src, $pg\t# KILL $tmp1, $tmp2, $tmp3, tmp4, $ptmp, $pgtmp" %} ins_encode %{ - uint length_in_bytes = Matcher::vector_length_in_bytes(this); __ sve_compress_byte($dst$$FloatRegister, $src$$FloatRegister, $pg$$PRegister, - $tmp1$$FloatRegister, $tmp2$$FloatRegister, $tmp3$$FloatRegister, - $ptmp$$PRegister, $pgtmp$$PRegister, length_in_bytes); + $tmp1$$FloatRegister,$tmp2$$FloatRegister, + $tmp3$$FloatRegister,$tmp4$$FloatRegister, + $ptmp$$PRegister, $pgtmp$$PRegister); %} ins_pipe(pipe_slow); %} -instruct vcompressS(vReg dst, vReg src, pReg pg, vReg tmp1, vReg tmp2, pRegGov pgtmp) %{ +instruct vcompressS(vReg dst, vReg src, pReg pg, + vReg tmp1, vReg tmp2, pRegGov pgtmp) %{ predicate(UseSVE > 0 && Matcher::vector_element_basic_type(n) == T_SHORT); effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2, TEMP pgtmp); match(Set dst (CompressV src pg)); format %{ "vcompressS $dst, $src, $pg\t# KILL $tmp1, $tmp2, $pgtmp" %} ins_encode %{ - uint length_in_bytes = Matcher::vector_length_in_bytes(this); - __ sve_dup($tmp1$$FloatRegister, __ H, 0); __ sve_compress_short($dst$$FloatRegister, $src$$FloatRegister, $pg$$PRegister, - $tmp1$$FloatRegister, $tmp2$$FloatRegister, $pgtmp$$PRegister, - length_in_bytes); + $tmp1$$FloatRegister,$tmp2$$FloatRegister, $pgtmp$$PRegister); %} ins_pipe(pipe_slow); %} diff --git a/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 b/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 index 6d296cbdb3ac3..012de7e46d809 100644 --- a/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 +++ b/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 @@ -5069,31 +5069,29 @@ instruct vcompress(vReg dst, vReg src, pRegGov pg) %{ %} instruct vcompressB(vReg dst, vReg src, pReg pg, vReg tmp1, vReg tmp2, - vReg tmp3, pReg ptmp, pRegGov pgtmp) %{ + vReg tmp3, vReg tmp4, pReg ptmp, pRegGov pgtmp) %{ predicate(UseSVE > 0 && Matcher::vector_element_basic_type(n) == T_BYTE); - effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP ptmp, TEMP pgtmp); + effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP ptmp, TEMP pgtmp); match(Set dst (CompressV src pg)); - format %{ "vcompressB $dst, $src, $pg\t# KILL $tmp1, $tmp2, $tmp3, $ptmp, $pgtmp" %} + format %{ "vcompressB $dst, $src, $pg\t# KILL $tmp1, $tmp2, $tmp3, tmp4, $ptmp, $pgtmp" %} ins_encode %{ - uint length_in_bytes = Matcher::vector_length_in_bytes(this); __ sve_compress_byte($dst$$FloatRegister, $src$$FloatRegister, $pg$$PRegister, - $tmp1$$FloatRegister, $tmp2$$FloatRegister, $tmp3$$FloatRegister, - $ptmp$$PRegister, $pgtmp$$PRegister, length_in_bytes); + $tmp1$$FloatRegister,$tmp2$$FloatRegister, + $tmp3$$FloatRegister,$tmp4$$FloatRegister, + $ptmp$$PRegister, $pgtmp$$PRegister); %} ins_pipe(pipe_slow); %} -instruct vcompressS(vReg dst, vReg src, pReg pg, vReg tmp1, vReg tmp2, pRegGov pgtmp) %{ +instruct vcompressS(vReg dst, vReg src, pReg pg, + vReg tmp1, vReg tmp2, pRegGov pgtmp) %{ predicate(UseSVE > 0 && Matcher::vector_element_basic_type(n) == T_SHORT); effect(TEMP_DEF dst, TEMP tmp1, TEMP tmp2, TEMP pgtmp); match(Set dst (CompressV src pg)); format %{ "vcompressS $dst, $src, $pg\t# KILL $tmp1, $tmp2, $pgtmp" %} ins_encode %{ - uint length_in_bytes = Matcher::vector_length_in_bytes(this); - __ sve_dup($tmp1$$FloatRegister, __ H, 0); __ sve_compress_short($dst$$FloatRegister, $src$$FloatRegister, $pg$$PRegister, - $tmp1$$FloatRegister, $tmp2$$FloatRegister, $pgtmp$$PRegister, - length_in_bytes); + $tmp1$$FloatRegister,$tmp2$$FloatRegister, $pgtmp$$PRegister); %} ins_pipe(pipe_slow); %} diff --git a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp index a8f378e524fc3..4c4251fbe9f25 100644 --- a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp @@ -3486,7 +3486,6 @@ template INSN(sve_smaxv, 0b00000100, 0b001000001); // signed maximum reduction to scalar INSN(sve_smin, 0b00000100, 0b001010000); // signed minimum vectors INSN(sve_sminv, 0b00000100, 0b001010001); // signed minimum reduction to scalar - INSN(sve_splice,0b00000101, 0b101100100); // splice two vectors under predicate control, destructive INSN(sve_sub, 0b00000100, 0b000001000); // vector sub INSN(sve_uaddv, 0b00000100, 0b000001001); // unsigned add reduction to scalar INSN(sve_umax, 0b00000100, 0b001001000); // unsigned maximum vectors diff --git a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp index 328ef0c53e6bd..b61a0e4e3789d 100644 --- a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp @@ -2203,117 +2203,114 @@ void C2_MacroAssembler::sve_gen_mask_imm(PRegister dst, BasicType bt, uint32_t l // Pack active elements of src, under the control of mask, into the lowest-numbered elements of dst. // Any remaining elements of dst will be filled with zero. // Clobbers: rscratch1 -// Preserves: mask, vzr +// Preserves: src, mask void C2_MacroAssembler::sve_compress_short(FloatRegister dst, FloatRegister src, PRegister mask, - FloatRegister vzr, FloatRegister vtmp, - PRegister pgtmp, unsigned vector_length_in_bytes) { + FloatRegister vtmp1, FloatRegister vtmp2, + PRegister pgtmp) { assert(pgtmp->is_governing(), "This register has to be a governing predicate register"); - // When called by sve_compress_byte, src and vtmp may be the same register. - assert_different_registers(dst, src, vzr); - assert_different_registers(dst, vtmp, vzr); + assert_different_registers(dst, src, vtmp1, vtmp2); assert_different_registers(mask, pgtmp); - // high <-- low - // Example input: src = hh gg ff ee dd cc bb aa, one character is 8 bits. - // mask = 01 00 00 01 01 00 01 01, one character is 1 bit. - // Expected result: dst = 00 00 00 hh ee dd bb aa + + // Example input: src = 8888 7777 6666 5555 4444 3333 2222 1111 + // mask = 0001 0000 0000 0001 0001 0000 0001 0001 + // Expected result: dst = 0000 0000 0000 8888 5555 4444 2222 1111 + sve_dup(vtmp2, H, 0); // Extend lowest half to type INT. - // dst = 00dd 00cc 00bb 00aa + // dst = 00004444 00003333 00002222 00001111 sve_uunpklo(dst, S, src); - // pgtmp = 0001 0000 0001 0001 + // pgtmp = 00000001 00000000 00000001 00000001 sve_punpklo(pgtmp, mask); // Pack the active elements in size of type INT to the right, // and fill the remainings with zero. - // dst = 0000 00dd 00bb 00aa + // dst = 00000000 00004444 00002222 00001111 sve_compact(dst, S, dst, pgtmp); // Narrow the result back to type SHORT. - // dst = 00 00 00 00 00 dd bb aa - sve_uzp1(dst, H, dst, vzr); - - // Return if the vector length is no more than MaxVectorSize/2, since the - // highest half is invalid. - if (vector_length_in_bytes <= (MaxVectorSize >> 1)) { - return; - } - + // dst = 0000 0000 0000 0000 0000 4444 2222 1111 + sve_uzp1(dst, H, dst, vtmp2); // Count the active elements of lowest half. // rscratch1 = 3 sve_cntp(rscratch1, S, ptrue, pgtmp); // Repeat to the highest half. - // pgtmp = 0001 0000 0000 0001 + // pgtmp = 00000001 00000000 00000000 00000001 sve_punpkhi(pgtmp, mask); - // vtmp = 00hh 00gg 00ff 00ee - sve_uunpkhi(vtmp, S, src); - // vtmp = 0000 0000 00hh 00ee - sve_compact(vtmp, S, vtmp, pgtmp); - // vtmp = 00 00 00 00 00 00 hh ee - sve_uzp1(vtmp, H, vtmp, vzr); - - // pgtmp = 00 00 00 00 00 01 01 01 - sve_whilelt(pgtmp, H, zr, rscratch1); - // Compressed low: dst = 00 00 00 00 00 dd bb aa - // Compressed high: vtmp = 00 00 00 00 00 00 hh ee - // Combine the compressed low with the compressed high: - // dst = 00 00 00 hh ee dd bb aa - sve_splice(dst, H, pgtmp, vtmp); + // vtmp1 = 00008888 00007777 00006666 00005555 + sve_uunpkhi(vtmp1, S, src); + // vtmp1 = 00000000 00000000 00008888 00005555 + sve_compact(vtmp1, S, vtmp1, pgtmp); + // vtmp1 = 0000 0000 0000 0000 0000 0000 8888 5555 + sve_uzp1(vtmp1, H, vtmp1, vtmp2); + + // Compressed low: dst = 0000 0000 0000 0000 0000 4444 2222 1111 + // Compressed high: vtmp1 = 0000 0000 0000 0000 0000 0000 8888 5555 + // Left shift(cross lane) compressed high with TRUE_CNT lanes, + // TRUE_CNT is the number of active elements in the compressed low. + neg(rscratch1, rscratch1); + // vtmp2 = {4 3 2 1 0 -1 -2 -3} + sve_index(vtmp2, H, rscratch1, 1); + // vtmp1 = 0000 0000 0000 8888 5555 0000 0000 0000 + sve_tbl(vtmp1, H, vtmp1, vtmp2); + + // Combine the compressed high(after shifted) with the compressed low. + // dst = 0000 0000 0000 8888 5555 4444 2222 1111 + sve_orr(dst, dst, vtmp1); } // Clobbers: rscratch1, rscratch2 // Preserves: src, mask void C2_MacroAssembler::sve_compress_byte(FloatRegister dst, FloatRegister src, PRegister mask, - FloatRegister vtmp1, FloatRegister vtmp2, FloatRegister vtmp3, - PRegister ptmp, PRegister pgtmp, unsigned vector_length_in_bytes) { + FloatRegister vtmp1, FloatRegister vtmp2, + FloatRegister vtmp3, FloatRegister vtmp4, + PRegister ptmp, PRegister pgtmp) { assert(pgtmp->is_governing(), "This register has to be a governing predicate register"); - assert_different_registers(dst, src, vtmp1, vtmp2, vtmp3); + assert_different_registers(dst, src, vtmp1, vtmp2, vtmp3, vtmp4); assert_different_registers(mask, ptmp, pgtmp); - // high <-- low - // Example input: src = q p n m l k j i h g f e d c b a, one character is 8 bits. - // mask = 0 1 0 0 0 0 0 1 0 1 0 0 0 1 0 1, one character is 1 bit. - // Expected result: dst = 0 0 0 0 0 0 0 0 0 0 0 p i g c a - FloatRegister vzr = vtmp3; - sve_dup(vzr, B, 0); + // Example input: src = 88 77 66 55 44 33 22 11 + // mask = 01 00 00 01 01 00 01 01 + // Expected result: dst = 00 00 00 88 55 44 22 11 + sve_dup(vtmp4, B, 0); // Extend lowest half to type SHORT. - // vtmp1 = 0h 0g 0f 0e 0d 0c 0b 0a + // vtmp1 = 0044 0033 0022 0011 sve_uunpklo(vtmp1, H, src); - // ptmp = 00 01 00 00 00 01 00 01 + // ptmp = 0001 0000 0001 0001 sve_punpklo(ptmp, mask); - // Pack the active elements in size of type SHORT to the right, - // and fill the remainings with zero. - // dst = 00 00 00 00 00 0g 0c 0a - unsigned extended_size = vector_length_in_bytes << 1; - sve_compress_short(dst, vtmp1, ptmp, vzr, vtmp2, pgtmp, extended_size > MaxVectorSize ? MaxVectorSize : extended_size); - // Narrow the result back to type BYTE. - // dst = 0 0 0 0 0 0 0 0 0 0 0 0 0 g c a - sve_uzp1(dst, B, dst, vzr); - - // Return if the vector length is no more than MaxVectorSize/2, since the - // highest half is invalid. - if (vector_length_in_bytes <= (MaxVectorSize >> 1)) { - return; - } // Count the active elements of lowest half. // rscratch2 = 3 sve_cntp(rscratch2, H, ptrue, ptmp); + // Pack the active elements in size of type SHORT to the right, + // and fill the remainings with zero. + // dst = 0000 0044 0022 0011 + sve_compress_short(dst, vtmp1, ptmp, vtmp2, vtmp3, pgtmp); + // Narrow the result back to type BYTE. + // dst = 00 00 00 00 00 44 22 11 + sve_uzp1(dst, B, dst, vtmp4); // Repeat to the highest half. - // ptmp = 00 01 00 00 00 00 00 01 + // ptmp = 0001 0000 0000 0001 sve_punpkhi(ptmp, mask); - // vtmp2 = 0q 0p 0n 0m 0l 0k 0j 0i + // vtmp1 = 0088 0077 0066 0055 sve_uunpkhi(vtmp2, H, src); - // vtmp1 = 00 00 00 00 00 00 0p 0i - sve_compress_short(vtmp1, vtmp2, ptmp, vzr, vtmp2, pgtmp, extended_size - MaxVectorSize); - // vtmp1 = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 p i - sve_uzp1(vtmp1, B, vtmp1, vzr); - - // ptmp = 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 - sve_whilelt(ptmp, B, zr, rscratch2); - // Compressed low: dst = 0 0 0 0 0 0 0 0 0 0 0 0 0 g c a - // Compressed high: vtmp1 = 0 0 0 0 0 0 0 0 0 0 0 0 0 0 p i - // Combine the compressed low with the compressed high: - // dst = 0 0 0 0 0 0 0 0 0 0 0 p i g c a - sve_splice(dst, B, ptmp, vtmp1); + // vtmp1 = 0000 0000 0088 0055 + sve_compress_short(vtmp1, vtmp2, ptmp, vtmp3, vtmp4, pgtmp); + + sve_dup(vtmp4, B, 0); + // vtmp1 = 00 00 00 00 00 00 88 55 + sve_uzp1(vtmp1, B, vtmp1, vtmp4); + + // Compressed low: dst = 00 00 00 00 00 44 22 11 + // Compressed high: vtmp1 = 00 00 00 00 00 00 88 55 + // Left shift(cross lane) compressed high with TRUE_CNT lanes, + // TRUE_CNT is the number of active elements in the compressed low. + neg(rscratch2, rscratch2); + // vtmp2 = {4 3 2 1 0 -1 -2 -3} + sve_index(vtmp2, B, rscratch2, 1); + // vtmp1 = 00 00 00 88 55 00 00 00 + sve_tbl(vtmp1, B, vtmp1, vtmp2); + // Combine the compressed high(after shifted) with the compressed low. + // dst = 00 00 00 88 55 44 22 11 + sve_orr(dst, dst, vtmp1); } void C2_MacroAssembler::neon_reverse_bits(FloatRegister dst, FloatRegister src, BasicType bt, bool isQ) { diff --git a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp index 09850a60c64d3..cb8ded142f48a 100644 --- a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.hpp @@ -173,12 +173,13 @@ // lowest-numbered elements of dst. Any remaining elements of dst will // be filled with zero. void sve_compress_byte(FloatRegister dst, FloatRegister src, PRegister mask, - FloatRegister vtmp1, FloatRegister vtmp2, FloatRegister vtmp3, - PRegister ptmp, PRegister pgtmp, unsigned vector_length_in_bytes); + FloatRegister vtmp1, FloatRegister vtmp2, + FloatRegister vtmp3, FloatRegister vtmp4, + PRegister ptmp, PRegister pgtmp); void sve_compress_short(FloatRegister dst, FloatRegister src, PRegister mask, - FloatRegister vzr, FloatRegister vtmp, - PRegister pgtmp, unsigned vector_length_in_bytes); + FloatRegister vtmp1, FloatRegister vtmp2, + PRegister pgtmp); void neon_reverse_bits(FloatRegister dst, FloatRegister src, BasicType bt, bool isQ); diff --git a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp index 6f8795494a2bb..607912e6e494f 100644 --- a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp @@ -1704,14 +1704,3 @@ void InterpreterMacroAssembler::load_method_entry(Register cache, Register index add(cache, cache, Array::base_offset_in_bytes()); lea(cache, Address(cache, index)); } - -#ifdef ASSERT -void InterpreterMacroAssembler::verify_field_offset(Register reg) { - // Verify the field offset is not in the header, implicitly checks for 0 - Label L; - subs(zr, reg, oopDesc::base_offset_in_bytes()); - br(Assembler::GE, L); - stop("bad field offset"); - bind(L); -} -#endif diff --git a/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp b/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp index e07e6e49f535d..e896a2a943041 100644 --- a/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp @@ -319,8 +319,6 @@ class InterpreterMacroAssembler: public MacroAssembler { void load_resolved_indy_entry(Register cache, Register index); void load_field_entry(Register cache, Register index, int bcp_offset = 1); void load_method_entry(Register cache, Register index, int bcp_offset = 1); - - void verify_field_offset(Register reg) NOT_DEBUG_RETURN; }; #endif // CPU_AARCH64_INTERP_MASM_AARCH64_HPP diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index 1400978931986..a37edab8578db 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -148,34 +148,56 @@ extern "C" void disnm(intptr_t p); // strictly should be 64 bit movz #imm16<<0 // 110___10100 (i.e. requires insn[31:21] == 11010010100) // +class RelocActions { +protected: + typedef int (*reloc_insn)(address insn_addr, address &target); -static uint32_t insn_at(address insn_addr, int n) { - return ((uint32_t*)insn_addr)[n]; -} + virtual reloc_insn adrpMem() = 0; + virtual reloc_insn adrpAdd() = 0; + virtual reloc_insn adrpMovk() = 0; + + const address _insn_addr; + const uint32_t _insn; -template -class RelocActions : public AllStatic { + static uint32_t insn_at(address insn_addr, int n) { + return ((uint32_t*)insn_addr)[n]; + } + uint32_t insn_at(int n) const { + return insn_at(_insn_addr, n); + } public: - static int ALWAYSINLINE run(address insn_addr, address &target) { + RelocActions(address insn_addr) : _insn_addr(insn_addr), _insn(insn_at(insn_addr, 0)) {} + RelocActions(address insn_addr, uint32_t insn) + : _insn_addr(insn_addr), _insn(insn) {} + + virtual int unconditionalBranch(address insn_addr, address &target) = 0; + virtual int conditionalBranch(address insn_addr, address &target) = 0; + virtual int testAndBranch(address insn_addr, address &target) = 0; + virtual int loadStore(address insn_addr, address &target) = 0; + virtual int adr(address insn_addr, address &target) = 0; + virtual int adrp(address insn_addr, address &target, reloc_insn inner) = 0; + virtual int immediate(address insn_addr, address &target) = 0; + virtual void verify(address insn_addr, address &target) = 0; + + int ALWAYSINLINE run(address insn_addr, address &target) { int instructions = 1; - uint32_t insn = insn_at(insn_addr, 0); - uint32_t dispatch = Instruction_aarch64::extract(insn, 30, 25); + uint32_t dispatch = Instruction_aarch64::extract(_insn, 30, 25); switch(dispatch) { case 0b001010: case 0b001011: { - instructions = T::unconditionalBranch(insn_addr, target); + instructions = unconditionalBranch(insn_addr, target); break; } case 0b101010: // Conditional branch (immediate) case 0b011010: { // Compare & branch (immediate) - instructions = T::conditionalBranch(insn_addr, target); - break; + instructions = conditionalBranch(insn_addr, target); + break; } case 0b011011: { - instructions = T::testAndBranch(insn_addr, target); + instructions = testAndBranch(insn_addr, target); break; } case 0b001100: @@ -187,9 +209,9 @@ class RelocActions : public AllStatic { case 0b111100: case 0b111110: { // load/store - if ((Instruction_aarch64::extract(insn, 29, 24) & 0b111011) == 0b011000) { + if ((Instruction_aarch64::extract(_insn, 29, 24) & 0b111011) == 0b011000) { // Load register (literal) - instructions = T::loadStore(insn_addr, target); + instructions = loadStore(insn_addr, target); break; } else { // nothing to do @@ -202,27 +224,27 @@ class RelocActions : public AllStatic { case 0b101000: case 0b111000: { // adr/adrp - assert(Instruction_aarch64::extract(insn, 28, 24) == 0b10000, "must be"); - int shift = Instruction_aarch64::extract(insn, 31, 31); + assert(Instruction_aarch64::extract(_insn, 28, 24) == 0b10000, "must be"); + int shift = Instruction_aarch64::extract(_insn, 31, 31); if (shift) { - uint32_t insn2 = insn_at(insn_addr, 1); + uint32_t insn2 = insn_at(1); if (Instruction_aarch64::extract(insn2, 29, 24) == 0b111001 && - Instruction_aarch64::extract(insn, 4, 0) == + Instruction_aarch64::extract(_insn, 4, 0) == Instruction_aarch64::extract(insn2, 9, 5)) { - instructions = T::adrp(insn_addr, target, T::adrpMem); + instructions = adrp(insn_addr, target, adrpMem()); } else if (Instruction_aarch64::extract(insn2, 31, 22) == 0b1001000100 && - Instruction_aarch64::extract(insn, 4, 0) == + Instruction_aarch64::extract(_insn, 4, 0) == Instruction_aarch64::extract(insn2, 4, 0)) { - instructions = T::adrp(insn_addr, target, T::adrpAdd); + instructions = adrp(insn_addr, target, adrpAdd()); } else if (Instruction_aarch64::extract(insn2, 31, 21) == 0b11110010110 && - Instruction_aarch64::extract(insn, 4, 0) == + Instruction_aarch64::extract(_insn, 4, 0) == Instruction_aarch64::extract(insn2, 4, 0)) { - instructions = T::adrp(insn_addr, target, T::adrpMovk); + instructions = adrp(insn_addr, target, adrpMovk()); } else { ShouldNotReachHere(); } } else { - instructions = T::adr(insn_addr, target); + instructions = adr(insn_addr, target); } break; } @@ -230,7 +252,7 @@ class RelocActions : public AllStatic { case 0b011001: case 0b101001: case 0b111001: { - instructions = T::immediate(insn_addr, target); + instructions = immediate(insn_addr, target); break; } default: { @@ -238,36 +260,42 @@ class RelocActions : public AllStatic { } } - T::verify(insn_addr, target); + verify(insn_addr, target); return instructions * NativeInstruction::instruction_size; } }; -class Patcher : public AllStatic { +class Patcher : public RelocActions { + virtual reloc_insn adrpMem() { return &Patcher::adrpMem_impl; } + virtual reloc_insn adrpAdd() { return &Patcher::adrpAdd_impl; } + virtual reloc_insn adrpMovk() { return &Patcher::adrpMovk_impl; } + public: - static int unconditionalBranch(address insn_addr, address &target) { + Patcher(address insn_addr) : RelocActions(insn_addr) {} + + virtual int unconditionalBranch(address insn_addr, address &target) { intptr_t offset = (target - insn_addr) >> 2; Instruction_aarch64::spatch(insn_addr, 25, 0, offset); return 1; } - static int conditionalBranch(address insn_addr, address &target) { + virtual int conditionalBranch(address insn_addr, address &target) { intptr_t offset = (target - insn_addr) >> 2; Instruction_aarch64::spatch(insn_addr, 23, 5, offset); return 1; } - static int testAndBranch(address insn_addr, address &target) { + virtual int testAndBranch(address insn_addr, address &target) { intptr_t offset = (target - insn_addr) >> 2; Instruction_aarch64::spatch(insn_addr, 18, 5, offset); return 1; } - static int loadStore(address insn_addr, address &target) { + virtual int loadStore(address insn_addr, address &target) { intptr_t offset = (target - insn_addr) >> 2; Instruction_aarch64::spatch(insn_addr, 23, 5, offset); return 1; } - static int adr(address insn_addr, address &target) { + virtual int adr(address insn_addr, address &target) { #ifdef ASSERT - assert(Instruction_aarch64::extract(insn_at(insn_addr, 0), 28, 24) == 0b10000, "must be"); + assert(Instruction_aarch64::extract(_insn, 28, 24) == 0b10000, "must be"); #endif // PC-rel. addressing ptrdiff_t offset = target - insn_addr; @@ -277,18 +305,17 @@ class Patcher : public AllStatic { Instruction_aarch64::patch(insn_addr, 30, 29, offset_lo); return 1; } - template - static int adrp(address insn_addr, address &target, U inner) { + virtual int adrp(address insn_addr, address &target, reloc_insn inner) { int instructions = 1; #ifdef ASSERT - assert(Instruction_aarch64::extract(insn_at(insn_addr, 0), 28, 24) == 0b10000, "must be"); + assert(Instruction_aarch64::extract(_insn, 28, 24) == 0b10000, "must be"); #endif ptrdiff_t offset = target - insn_addr; instructions = 2; precond(inner != nullptr); // Give the inner reloc a chance to modify the target. address adjusted_target = target; - instructions = inner(insn_addr, adjusted_target); + instructions = (*inner)(insn_addr, adjusted_target); uintptr_t pc_page = (uintptr_t)insn_addr >> 12; uintptr_t adr_page = (uintptr_t)adjusted_target >> 12; offset = adr_page - pc_page; @@ -298,7 +325,7 @@ class Patcher : public AllStatic { Instruction_aarch64::patch(insn_addr, 30, 29, offset_lo); return instructions; } - static int adrpMem(address insn_addr, address &target) { + static int adrpMem_impl(address insn_addr, address &target) { uintptr_t dest = (uintptr_t)target; int offset_lo = dest & 0xfff; uint32_t insn2 = insn_at(insn_addr, 1); @@ -307,21 +334,21 @@ class Patcher : public AllStatic { guarantee(((dest >> size) << size) == dest, "misaligned target"); return 2; } - static int adrpAdd(address insn_addr, address &target) { + static int adrpAdd_impl(address insn_addr, address &target) { uintptr_t dest = (uintptr_t)target; int offset_lo = dest & 0xfff; Instruction_aarch64::patch(insn_addr + sizeof (uint32_t), 21, 10, offset_lo); return 2; } - static int adrpMovk(address insn_addr, address &target) { + static int adrpMovk_impl(address insn_addr, address &target) { uintptr_t dest = uintptr_t(target); Instruction_aarch64::patch(insn_addr + sizeof (uint32_t), 20, 5, (uintptr_t)target >> 32); dest = (dest & 0xffffffffULL) | (uintptr_t(insn_addr) & 0xffff00000000ULL); target = address(dest); return 2; } - static int immediate(address insn_addr, address &target) { - assert(Instruction_aarch64::extract(insn_at(insn_addr, 0), 31, 21) == 0b11010010100, "must be"); + virtual int immediate(address insn_addr, address &target) { + assert(Instruction_aarch64::extract(_insn, 31, 21) == 0b11010010100, "must be"); uint64_t dest = (uint64_t)target; // Move wide constant assert(nativeInstruction_at(insn_addr+4)->is_movk(), "wrong insns in patch"); @@ -331,7 +358,7 @@ class Patcher : public AllStatic { Instruction_aarch64::patch(insn_addr+8, 20, 5, (dest >>= 16) & 0xffff); return 3; } - static void verify(address insn_addr, address &target) { + virtual void verify(address insn_addr, address &target) { #ifdef ASSERT address address_is = MacroAssembler::target_addr_for_insn(insn_addr); if (!(address_is == target)) { @@ -365,54 +392,56 @@ static bool offset_for(uint32_t insn1, uint32_t insn2, ptrdiff_t &byte_offset) { return false; } -class AArch64Decoder : public AllStatic { +class AArch64Decoder : public RelocActions { + virtual reloc_insn adrpMem() { return &AArch64Decoder::adrpMem_impl; } + virtual reloc_insn adrpAdd() { return &AArch64Decoder::adrpAdd_impl; } + virtual reloc_insn adrpMovk() { return &AArch64Decoder::adrpMovk_impl; } + public: + AArch64Decoder(address insn_addr, uint32_t insn) : RelocActions(insn_addr, insn) {} - static int loadStore(address insn_addr, address &target) { - intptr_t offset = Instruction_aarch64::sextract(insn_at(insn_addr, 0), 23, 5); + virtual int loadStore(address insn_addr, address &target) { + intptr_t offset = Instruction_aarch64::sextract(_insn, 23, 5); target = insn_addr + (offset << 2); return 1; } - static int unconditionalBranch(address insn_addr, address &target) { - intptr_t offset = Instruction_aarch64::sextract(insn_at(insn_addr, 0), 25, 0); + virtual int unconditionalBranch(address insn_addr, address &target) { + intptr_t offset = Instruction_aarch64::sextract(_insn, 25, 0); target = insn_addr + (offset << 2); return 1; } - static int conditionalBranch(address insn_addr, address &target) { - intptr_t offset = Instruction_aarch64::sextract(insn_at(insn_addr, 0), 23, 5); + virtual int conditionalBranch(address insn_addr, address &target) { + intptr_t offset = Instruction_aarch64::sextract(_insn, 23, 5); target = address(((uint64_t)insn_addr + (offset << 2))); return 1; } - static int testAndBranch(address insn_addr, address &target) { - intptr_t offset = Instruction_aarch64::sextract(insn_at(insn_addr, 0), 18, 5); + virtual int testAndBranch(address insn_addr, address &target) { + intptr_t offset = Instruction_aarch64::sextract(_insn, 18, 5); target = address(((uint64_t)insn_addr + (offset << 2))); return 1; } - static int adr(address insn_addr, address &target) { + virtual int adr(address insn_addr, address &target) { // PC-rel. addressing - uint32_t insn = insn_at(insn_addr, 0); - intptr_t offset = Instruction_aarch64::extract(insn, 30, 29); - offset |= Instruction_aarch64::sextract(insn, 23, 5) << 2; + intptr_t offset = Instruction_aarch64::extract(_insn, 30, 29); + offset |= Instruction_aarch64::sextract(_insn, 23, 5) << 2; target = address((uint64_t)insn_addr + offset); return 1; } - template - static int adrp(address insn_addr, address &target, U inner) { - uint32_t insn = insn_at(insn_addr, 0); - assert(Instruction_aarch64::extract(insn, 28, 24) == 0b10000, "must be"); - intptr_t offset = Instruction_aarch64::extract(insn, 30, 29); - offset |= Instruction_aarch64::sextract(insn, 23, 5) << 2; + virtual int adrp(address insn_addr, address &target, reloc_insn inner) { + assert(Instruction_aarch64::extract(_insn, 28, 24) == 0b10000, "must be"); + intptr_t offset = Instruction_aarch64::extract(_insn, 30, 29); + offset |= Instruction_aarch64::sextract(_insn, 23, 5) << 2; int shift = 12; offset <<= shift; uint64_t target_page = ((uint64_t)insn_addr) + offset; target_page &= ((uint64_t)-1) << shift; - uint32_t insn2 = insn_at(insn_addr, 1); + uint32_t insn2 = insn_at(1); target = address(target_page); precond(inner != nullptr); - inner(insn_addr, target); + (*inner)(insn_addr, target); return 2; } - static int adrpMem(address insn_addr, address &target) { + static int adrpMem_impl(address insn_addr, address &target) { uint32_t insn2 = insn_at(insn_addr, 1); // Load/store register (unsigned immediate) ptrdiff_t byte_offset = Instruction_aarch64::extract(insn2, 21, 10); @@ -421,14 +450,14 @@ class AArch64Decoder : public AllStatic { target += byte_offset; return 2; } - static int adrpAdd(address insn_addr, address &target) { + static int adrpAdd_impl(address insn_addr, address &target) { uint32_t insn2 = insn_at(insn_addr, 1); // add (immediate) ptrdiff_t byte_offset = Instruction_aarch64::extract(insn2, 21, 10); target += byte_offset; return 2; } - static int adrpMovk(address insn_addr, address &target) { + static int adrpMovk_impl(address insn_addr, address &target) { uint32_t insn2 = insn_at(insn_addr, 1); uint64_t dest = uint64_t(target); dest = (dest & 0xffff0000ffffffff) | @@ -447,33 +476,35 @@ class AArch64Decoder : public AllStatic { return 2; } } - static int immediate(address insn_addr, address &target) { + virtual int immediate(address insn_addr, address &target) { uint32_t *insns = (uint32_t *)insn_addr; - assert(Instruction_aarch64::extract(insns[0], 31, 21) == 0b11010010100, "must be"); + assert(Instruction_aarch64::extract(_insn, 31, 21) == 0b11010010100, "must be"); // Move wide constant: movz, movk, movk. See movptr(). assert(nativeInstruction_at(insns+1)->is_movk(), "wrong insns in patch"); assert(nativeInstruction_at(insns+2)->is_movk(), "wrong insns in patch"); - target = address(uint64_t(Instruction_aarch64::extract(insns[0], 20, 5)) - + (uint64_t(Instruction_aarch64::extract(insns[1], 20, 5)) << 16) - + (uint64_t(Instruction_aarch64::extract(insns[2], 20, 5)) << 32)); + target = address(uint64_t(Instruction_aarch64::extract(_insn, 20, 5)) + + (uint64_t(Instruction_aarch64::extract(insns[1], 20, 5)) << 16) + + (uint64_t(Instruction_aarch64::extract(insns[2], 20, 5)) << 32)); assert(nativeInstruction_at(insn_addr+4)->is_movk(), "wrong insns in patch"); assert(nativeInstruction_at(insn_addr+8)->is_movk(), "wrong insns in patch"); return 3; } - static void verify(address insn_addr, address &target) { + virtual void verify(address insn_addr, address &target) { } }; -address MacroAssembler::target_addr_for_insn(address insn_addr) { +address MacroAssembler::target_addr_for_insn(address insn_addr, uint32_t insn) { + AArch64Decoder decoder(insn_addr, insn); address target; - RelocActions::run(insn_addr, target); + decoder.run(insn_addr, target); return target; } // Patch any kind of instruction; there may be several instructions. // Return the total length (in bytes) of the instructions. int MacroAssembler::pd_patch_instruction_size(address insn_addr, address target) { - return RelocActions::run(insn_addr, target); + Patcher patcher(insn_addr); + return patcher.run(insn_addr, target); } int MacroAssembler::patch_oop(address insn_addr, address o) { @@ -515,11 +546,11 @@ int MacroAssembler::patch_narrow_klass(address insn_addr, narrowKlass n) { return 2 * NativeInstruction::instruction_size; } -address MacroAssembler::target_addr_for_insn_or_null(address insn_addr) { - if (NativeInstruction::is_ldrw_to_zr(insn_addr)) { +address MacroAssembler::target_addr_for_insn_or_null(address insn_addr, unsigned insn) { + if (NativeInstruction::is_ldrw_to_zr(address(&insn))) { return nullptr; } - return MacroAssembler::target_addr_for_insn(insn_addr); + return MacroAssembler::target_addr_for_insn(insn_addr, insn); } void MacroAssembler::safepoint_poll(Label& slow_path, bool at_return, bool in_nmethod, Register tmp) { diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp index d5a16e424e428..705bd19093c1d 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp @@ -676,8 +676,16 @@ class MacroAssembler: public Assembler { static bool needs_explicit_null_check(intptr_t offset); static bool uses_implicit_null_check(void* address); - static address target_addr_for_insn(address insn_addr); - static address target_addr_for_insn_or_null(address insn_addr); + static address target_addr_for_insn(address insn_addr, unsigned insn); + static address target_addr_for_insn_or_null(address insn_addr, unsigned insn); + static address target_addr_for_insn(address insn_addr) { + unsigned insn = *(unsigned*)insn_addr; + return target_addr_for_insn(insn_addr, insn); + } + static address target_addr_for_insn_or_null(address insn_addr) { + unsigned insn = *(unsigned*)insn_addr; + return target_addr_for_insn_or_null(insn_addr, insn); + } // Required platform-specific helpers for Label::patch_instructions. // They _shadow_ the declarations in AbstractAssembler, which are undefined. diff --git a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp index f4774f31bbd42..5195432f54ea2 100644 --- a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp @@ -168,7 +168,6 @@ void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg, Register temp_reg, bool load_bc_into_bc_reg/*=true*/, int byte_no) { - assert_different_registers(bc_reg, temp_reg); if (!RewriteBytecodes) return; Label L_patch_done; @@ -232,12 +231,9 @@ void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg, __ stop("patching the wrong bytecode"); __ bind(L_okay); #endif - // Patch bytecode with release store to coordinate with ResolvedFieldEntry loads - // in fast bytecode codelets. load_field_entry has a memory barrier that gains - // the needed ordering, together with control dependency on entering the fast codelet - // itself. - __ lea(temp_reg, at_bcp(0)); - __ stlrb(bc_reg, temp_reg); + + // patch bytecode + __ strb(bc_reg, at_bcp(0)); __ bind(L_patch_done); } @@ -3098,7 +3094,6 @@ void TemplateTable::fast_storefield(TosState state) // R1: field offset, R2: field holder, R5: flags load_resolved_field_entry(r2, r2, noreg, r1, r5); - __ verify_field_offset(r1); { Label notVolatile; @@ -3188,8 +3183,6 @@ void TemplateTable::fast_accessfield(TosState state) __ load_field_entry(r2, r1); __ load_sized_value(r1, Address(r2, in_bytes(ResolvedFieldEntry::field_offset_offset())), sizeof(int), true /*is_signed*/); - __ verify_field_offset(r1); - __ load_unsigned_byte(r3, Address(r2, in_bytes(ResolvedFieldEntry::flags_offset()))); // r0: object @@ -3256,9 +3249,7 @@ void TemplateTable::fast_xaccess(TosState state) __ ldr(r0, aaddress(0)); // access constant pool cache __ load_field_entry(r2, r3, 2); - __ load_sized_value(r1, Address(r2, in_bytes(ResolvedFieldEntry::field_offset_offset())), sizeof(int), true /*is_signed*/); - __ verify_field_offset(r1); // 8179954: We need to make sure that the code generated for // volatile accesses forms a sequentially-consistent set of diff --git a/src/hotspot/cpu/arm/arm.ad b/src/hotspot/cpu/arm/arm.ad index 31a442be62456..68fece5263d34 100644 --- a/src/hotspot/cpu/arm/arm.ad +++ b/src/hotspot/cpu/arm/arm.ad @@ -1131,27 +1131,27 @@ bool Matcher::use_asm_for_ldiv_by_con( jlong divisor ) { } // Register for DIVI projection of divmodI -const RegMask& Matcher::divI_proj_mask() { +RegMask Matcher::divI_proj_mask() { ShouldNotReachHere(); - return RegMask::EMPTY; + return RegMask(); } // Register for MODI projection of divmodI -const RegMask& Matcher::modI_proj_mask() { +RegMask Matcher::modI_proj_mask() { ShouldNotReachHere(); - return RegMask::EMPTY; + return RegMask(); } // Register for DIVL projection of divmodL -const RegMask& Matcher::divL_proj_mask() { +RegMask Matcher::divL_proj_mask() { ShouldNotReachHere(); - return RegMask::EMPTY; + return RegMask(); } // Register for MODL projection of divmodL -const RegMask& Matcher::modL_proj_mask() { +RegMask Matcher::modL_proj_mask() { ShouldNotReachHere(); - return RegMask::EMPTY; + return RegMask(); } bool maybe_far_call(const CallNode *n) { diff --git a/src/hotspot/cpu/ppc/interp_masm_ppc.hpp b/src/hotspot/cpu/ppc/interp_masm_ppc.hpp index 9140dd7ca4edf..d3969427db300 100644 --- a/src/hotspot/cpu/ppc/interp_masm_ppc.hpp +++ b/src/hotspot/cpu/ppc/interp_masm_ppc.hpp @@ -133,13 +133,8 @@ class InterpreterMacroAssembler: public MacroAssembler { void get_cache_index_at_bcp(Register Rdst, int bcp_offset, size_t index_size); void load_resolved_indy_entry(Register cache, Register index); - void load_field_or_method_entry(bool is_method, Register cache, Register index, int bcp_offset, bool for_fast_bytecode); - void load_field_entry(Register cache, Register index, int bcp_offset = 1, bool for_fast_bytecode = false) { - load_field_or_method_entry(false, cache, index, bcp_offset, for_fast_bytecode); - } - void load_method_entry(Register cache, Register index, int bcp_offset = 1, bool for_fast_bytecode = false) { - load_field_or_method_entry(true, cache, index, bcp_offset, for_fast_bytecode); - } + void load_field_entry(Register cache, Register index, int bcp_offset = 1); + void load_method_entry(Register cache, Register index, int bcp_offset = 1); void get_u4(Register Rdst, Register Rsrc, int offset, signedOrNot is_signed); diff --git a/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp b/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp index 503cc25943253..8df2cc5d273ff 100644 --- a/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp +++ b/src/hotspot/cpu/ppc/interp_masm_ppc_64.cpp @@ -468,33 +468,33 @@ void InterpreterMacroAssembler::load_resolved_indy_entry(Register cache, Registe add(cache, cache, index); } -void InterpreterMacroAssembler::load_field_or_method_entry(bool is_method, Register cache, Register index, int bcp_offset, bool for_fast_bytecode) { - const int entry_size = is_method ? sizeof(ResolvedMethodEntry) : sizeof(ResolvedFieldEntry), - base_offset = is_method ? Array::base_offset_in_bytes() : Array::base_offset_in_bytes(), - entries_offset = is_method ? in_bytes(ConstantPoolCache::method_entries_offset()) : in_bytes(ConstantPoolCache::field_entries_offset()); - +void InterpreterMacroAssembler::load_field_entry(Register cache, Register index, int bcp_offset) { // Get index out of bytecode pointer get_cache_index_at_bcp(index, bcp_offset, sizeof(u2)); // Take shortcut if the size is a power of 2 - if (is_power_of_2(entry_size)) { + if (is_power_of_2(sizeof(ResolvedFieldEntry))) { // Scale index by power of 2 - sldi(index, index, log2i_exact(entry_size)); + sldi(index, index, log2i_exact(sizeof(ResolvedFieldEntry))); } else { // Scale the index to be the entry index * sizeof(ResolvedFieldEntry) - mulli(index, index, entry_size); + mulli(index, index, sizeof(ResolvedFieldEntry)); } // Get address of field entries array - ld_ptr(cache, entries_offset, R27_constPoolCache); - addi(cache, cache, base_offset); + ld_ptr(cache, in_bytes(ConstantPoolCache::field_entries_offset()), R27_constPoolCache); + addi(cache, cache, Array::base_offset_in_bytes()); add(cache, cache, index); +} - if (for_fast_bytecode) { - // Prevent speculative loading from ResolvedFieldEntry/ResolvedMethodEntry as it can miss the info written by another thread. - // TemplateTable::patch_bytecode uses release-store. - // We reached here via control dependency (Bytecode dispatch has used the rewritten Bytecode). - // So, we can use control-isync based ordering. - isync(); - } +void InterpreterMacroAssembler::load_method_entry(Register cache, Register index, int bcp_offset) { + // Get index out of bytecode pointer + get_cache_index_at_bcp(index, bcp_offset, sizeof(u2)); + // Scale the index to be the entry index * sizeof(ResolvedMethodEntry) + mulli(index, index, sizeof(ResolvedMethodEntry)); + + // Get address of field entries array + ld_ptr(cache, ConstantPoolCache::method_entries_offset(), R27_constPoolCache); + addi(cache, cache, Array::base_offset_in_bytes()); + add(cache, cache, index); // method_entries + base_offset + scaled index } // Load object from cpool->resolved_references(index). diff --git a/src/hotspot/cpu/ppc/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad index 03dbd0e780ba2..2c83b2d576589 100644 --- a/src/hotspot/cpu/ppc/ppc.ad +++ b/src/hotspot/cpu/ppc/ppc.ad @@ -2450,27 +2450,27 @@ bool Matcher::use_asm_for_ldiv_by_con(jlong divisor) { } // Register for DIVI projection of divmodI. -const RegMask& Matcher::divI_proj_mask() { +RegMask Matcher::divI_proj_mask() { ShouldNotReachHere(); - return RegMask::EMPTY; + return RegMask(); } // Register for MODI projection of divmodI. -const RegMask& Matcher::modI_proj_mask() { +RegMask Matcher::modI_proj_mask() { ShouldNotReachHere(); - return RegMask::EMPTY; + return RegMask(); } // Register for DIVL projection of divmodL. -const RegMask& Matcher::divL_proj_mask() { +RegMask Matcher::divL_proj_mask() { ShouldNotReachHere(); - return RegMask::EMPTY; + return RegMask(); } // Register for MODL projection of divmodL. -const RegMask& Matcher::modL_proj_mask() { +RegMask Matcher::modL_proj_mask() { ShouldNotReachHere(); - return RegMask::EMPTY; + return RegMask(); } %} diff --git a/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp b/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp index 09acd1c067da9..41fbe66647ecc 100644 --- a/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp +++ b/src/hotspot/cpu/ppc/templateTable_ppc_64.cpp @@ -148,9 +148,7 @@ void TemplateTable::patch_bytecode(Bytecodes::Code new_bc, Register Rnew_bc, Reg __ bind(L_fast_patch); } - // Patch bytecode with release store to coordinate with ResolvedFieldEntry - // and ResolvedMethodEntry loads in fast bytecode codelets. - __ release(); + // Patch bytecode. __ stb(Rnew_bc, 0, R14_bcp); __ bind(L_patch_done); @@ -314,7 +312,6 @@ void TemplateTable::fast_aldc(LdcType type) { // We are resolved if the resolved reference cache entry contains a // non-null object (CallSite, etc.) __ get_cache_index_at_bcp(R31, 1, index_size); // Load index. - // Only rewritten during link time. So, no need for memory barriers for accessing resolved info. __ load_resolved_reference_at_index(R17_tos, R31, R11_scratch1, R12_scratch2, &is_null); // Convert null sentinel to null @@ -3117,7 +3114,7 @@ void TemplateTable::fast_storefield(TosState state) { const ConditionRegister CR_is_vol = CR2; // Non-volatile condition register (survives runtime call in do_oop_store). // Constant pool already resolved => Load flags and offset of field. - __ load_field_entry(Rcache, Rscratch, 1, /* for_fast_bytecode */ true); + __ load_field_entry(Rcache, Rscratch); jvmti_post_field_mod(Rcache, Rscratch, false /* not static */); load_resolved_field_entry(noreg, Rcache, noreg, Roffset, Rflags, false); // Uses R11, R12 @@ -3198,7 +3195,7 @@ void TemplateTable::fast_accessfield(TosState state) { // R12_scratch2 used by load_field_cp_cache_entry // Constant pool already resolved. Get the field offset. - __ load_field_entry(Rcache, Rscratch, 1, /* for_fast_bytecode */ true); + __ load_field_entry(Rcache, Rscratch); load_resolved_field_entry(noreg, Rcache, noreg, Roffset, Rflags, false); // Uses R11, R12 // JVMTI support @@ -3337,7 +3334,7 @@ void TemplateTable::fast_xaccess(TosState state) { __ ld(Rclass_or_obj, 0, R18_locals); // Constant pool already resolved. Get the field offset. - __ load_field_entry(Rcache, Rscratch, 2, /* for_fast_bytecode */ true); + __ load_field_entry(Rcache, Rscratch, 2); load_resolved_field_entry(noreg, Rcache, noreg, Roffset, Rflags, false); // Uses R11, R12 // JVMTI support not needed, since we switch back to single bytecode as soon as debugger attaches. @@ -3498,7 +3495,7 @@ void TemplateTable::fast_invokevfinal(int byte_no) { assert(byte_no == f2_byte, "use this argument"); Register Rcache = R31; - __ load_method_entry(Rcache, R11_scratch1, 1, /* for_fast_bytecode */ true); + __ load_method_entry(Rcache, R11_scratch1); invokevfinal_helper(Rcache, R11_scratch1, R12_scratch2, R22_tmp2, R23_tmp3); } diff --git a/src/hotspot/cpu/ppc/vm_version_ppc.cpp b/src/hotspot/cpu/ppc/vm_version_ppc.cpp index 8b1de7546506f..e2dfd4ecec97c 100644 --- a/src/hotspot/cpu/ppc/vm_version_ppc.cpp +++ b/src/hotspot/cpu/ppc/vm_version_ppc.cpp @@ -99,10 +99,6 @@ void VM_Version::initialize() { FLAG_SET_ERGO(TrapBasedRangeChecks, false); } - if (FLAG_IS_DEFAULT(UsePopCountInstruction)) { - FLAG_SET_ERGO(UsePopCountInstruction, true); - } - if (PowerArchitecturePPC64 >= 9) { // Performance is good since Power9. if (FLAG_IS_DEFAULT(SuperwordUseVSX)) { diff --git a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp index 549c9cda7b611..7c4b844440738 100644 --- a/src/hotspot/cpu/riscv/interp_masm_riscv.cpp +++ b/src/hotspot/cpu/riscv/interp_masm_riscv.cpp @@ -1841,15 +1841,6 @@ void InterpreterMacroAssembler::load_method_entry(Register cache, Register index } #ifdef ASSERT -void InterpreterMacroAssembler::verify_field_offset(Register reg) { - // Verify the field offset is not in the header, implicitly checks for 0 - Label L; - mv(t0, oopDesc::base_offset_in_bytes()); - bge(reg, t0, L); - stop("bad field offset"); - bind(L); -} - void InterpreterMacroAssembler::verify_access_flags(Register access_flags, uint32_t flag, const char* msg, bool stop_by_hit) { Label L; diff --git a/src/hotspot/cpu/riscv/interp_masm_riscv.hpp b/src/hotspot/cpu/riscv/interp_masm_riscv.hpp index 295f1b221916c..0732191ea83a1 100644 --- a/src/hotspot/cpu/riscv/interp_masm_riscv.hpp +++ b/src/hotspot/cpu/riscv/interp_masm_riscv.hpp @@ -300,10 +300,11 @@ class InterpreterMacroAssembler: public MacroAssembler { void load_field_entry(Register cache, Register index, int bcp_offset = 1); void load_method_entry(Register cache, Register index, int bcp_offset = 1); - void verify_field_offset(Register reg) NOT_DEBUG_RETURN; +#ifdef ASSERT void verify_access_flags(Register access_flags, uint32_t flag, - const char* msg, bool stop_by_hit = true) NOT_DEBUG_RETURN; - void verify_frame_setup() NOT_DEBUG_RETURN; + const char* msg, bool stop_by_hit = true); + void verify_frame_setup(); +#endif }; #endif // CPU_RISCV_INTERP_MASM_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad index 83c59af9113e9..009acd628a0d2 100644 --- a/src/hotspot/cpu/riscv/riscv.ad +++ b/src/hotspot/cpu/riscv/riscv.ad @@ -1092,40 +1092,40 @@ RegMask _NO_SPECIAL_NO_FP_PTR_REG_mask; void reg_mask_init() { - _ANY_REG32_mask.assignFrom(_ALL_REG32_mask); - _ANY_REG32_mask.remove(OptoReg::as_OptoReg(x0->as_VMReg())); + _ANY_REG32_mask = _ALL_REG32_mask; + _ANY_REG32_mask.Remove(OptoReg::as_OptoReg(x0->as_VMReg())); - _ANY_REG_mask.assignFrom(_ALL_REG_mask); - _ANY_REG_mask.subtract(_ZR_REG_mask); + _ANY_REG_mask = _ALL_REG_mask; + _ANY_REG_mask.SUBTRACT(_ZR_REG_mask); - _PTR_REG_mask.assignFrom(_ALL_REG_mask); - _PTR_REG_mask.subtract(_ZR_REG_mask); + _PTR_REG_mask = _ALL_REG_mask; + _PTR_REG_mask.SUBTRACT(_ZR_REG_mask); - _NO_SPECIAL_REG32_mask.assignFrom(_ALL_REG32_mask); - _NO_SPECIAL_REG32_mask.subtract(_NON_ALLOCATABLE_REG32_mask); + _NO_SPECIAL_REG32_mask = _ALL_REG32_mask; + _NO_SPECIAL_REG32_mask.SUBTRACT(_NON_ALLOCATABLE_REG32_mask); - _NO_SPECIAL_REG_mask.assignFrom(_ALL_REG_mask); - _NO_SPECIAL_REG_mask.subtract(_NON_ALLOCATABLE_REG_mask); + _NO_SPECIAL_REG_mask = _ALL_REG_mask; + _NO_SPECIAL_REG_mask.SUBTRACT(_NON_ALLOCATABLE_REG_mask); - _NO_SPECIAL_PTR_REG_mask.assignFrom(_ALL_REG_mask); - _NO_SPECIAL_PTR_REG_mask.subtract(_NON_ALLOCATABLE_REG_mask); + _NO_SPECIAL_PTR_REG_mask = _ALL_REG_mask; + _NO_SPECIAL_PTR_REG_mask.SUBTRACT(_NON_ALLOCATABLE_REG_mask); // x27 is not allocatable when compressed oops is on if (UseCompressedOops) { - _NO_SPECIAL_REG32_mask.remove(OptoReg::as_OptoReg(x27->as_VMReg())); - _NO_SPECIAL_REG_mask.remove(OptoReg::as_OptoReg(x27->as_VMReg())); - _NO_SPECIAL_PTR_REG_mask.remove(OptoReg::as_OptoReg(x27->as_VMReg())); + _NO_SPECIAL_REG32_mask.Remove(OptoReg::as_OptoReg(x27->as_VMReg())); + _NO_SPECIAL_REG_mask.Remove(OptoReg::as_OptoReg(x27->as_VMReg())); + _NO_SPECIAL_PTR_REG_mask.Remove(OptoReg::as_OptoReg(x27->as_VMReg())); } // x8 is not allocatable when PreserveFramePointer is on if (PreserveFramePointer) { - _NO_SPECIAL_REG32_mask.remove(OptoReg::as_OptoReg(x8->as_VMReg())); - _NO_SPECIAL_REG_mask.remove(OptoReg::as_OptoReg(x8->as_VMReg())); - _NO_SPECIAL_PTR_REG_mask.remove(OptoReg::as_OptoReg(x8->as_VMReg())); + _NO_SPECIAL_REG32_mask.Remove(OptoReg::as_OptoReg(x8->as_VMReg())); + _NO_SPECIAL_REG_mask.Remove(OptoReg::as_OptoReg(x8->as_VMReg())); + _NO_SPECIAL_PTR_REG_mask.Remove(OptoReg::as_OptoReg(x8->as_VMReg())); } - _NO_SPECIAL_NO_FP_PTR_REG_mask.assignFrom(_NO_SPECIAL_PTR_REG_mask); - _NO_SPECIAL_NO_FP_PTR_REG_mask.remove(OptoReg::as_OptoReg(x8->as_VMReg())); + _NO_SPECIAL_NO_FP_PTR_REG_mask = _NO_SPECIAL_PTR_REG_mask; + _NO_SPECIAL_NO_FP_PTR_REG_mask.Remove(OptoReg::as_OptoReg(x8->as_VMReg())); } void PhaseOutput::pd_perform_mach_node_analysis() { @@ -1326,7 +1326,7 @@ uint MachBreakpointNode::size(PhaseRegAlloc *ra_) const { } //============================================================================= -const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::EMPTY; +const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::Empty; int ConstantTable::calculate_table_base_offset() const { return 0; // absolute addressing, no offset @@ -2104,10 +2104,10 @@ uint Matcher::int_pressure_limit() // as a spilled LRG. Spilling heuristics(Spill-USE) explicitly skip // derived pointers and lastly fail to spill after reaching maximum // number of iterations. Lowering the default pressure threshold to - // (_NO_SPECIAL_REG32_mask.size() minus 1) forces CallNode to become + // (_NO_SPECIAL_REG32_mask.Size() minus 1) forces CallNode to become // a high register pressure area of the code so that split_DEF can // generate DefinitionSpillCopy for the derived pointer. - uint default_int_pressure_threshold = _NO_SPECIAL_REG32_mask.size() - 1; + uint default_int_pressure_threshold = _NO_SPECIAL_REG32_mask.Size() - 1; if (!PreserveFramePointer) { // When PreserveFramePointer is off, frame pointer is allocatable, // but different from other SOC registers, it is excluded from @@ -2122,34 +2122,34 @@ uint Matcher::int_pressure_limit() uint Matcher::float_pressure_limit() { // _FLOAT_REG_mask is generated by adlc from the float_reg register class. - return (FLOATPRESSURE == -1) ? _FLOAT_REG_mask.size() : FLOATPRESSURE; + return (FLOATPRESSURE == -1) ? _FLOAT_REG_mask.Size() : FLOATPRESSURE; } bool Matcher::use_asm_for_ldiv_by_con(jlong divisor) { return false; } -const RegMask& Matcher::divI_proj_mask() { +RegMask Matcher::divI_proj_mask() { ShouldNotReachHere(); - return RegMask::EMPTY; + return RegMask(); } // Register for MODI projection of divmodI. -const RegMask& Matcher::modI_proj_mask() { +RegMask Matcher::modI_proj_mask() { ShouldNotReachHere(); - return RegMask::EMPTY; + return RegMask(); } // Register for DIVL projection of divmodL. -const RegMask& Matcher::divL_proj_mask() { +RegMask Matcher::divL_proj_mask() { ShouldNotReachHere(); - return RegMask::EMPTY; + return RegMask(); } // Register for MODL projection of divmodL. -const RegMask& Matcher::modL_proj_mask() { +RegMask Matcher::modL_proj_mask() { ShouldNotReachHere(); - return RegMask::EMPTY; + return RegMask(); } bool size_fits_all_mem_uses(AddPNode* addp, int shift) { diff --git a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp index 692335d8c084a..61f4aa3e722a2 100644 --- a/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp +++ b/src/hotspot/cpu/riscv/templateInterpreterGenerator_riscv.cpp @@ -1073,7 +1073,9 @@ address TemplateInterpreterGenerator::generate_native_entry(bool synchronized) { } // start execution +#ifdef ASSERT __ verify_frame_setup(); +#endif // jvmti support __ notify_method_entry(); @@ -1539,7 +1541,9 @@ address TemplateInterpreterGenerator::generate_normal_entry(bool synchronized) { } // start execution +#ifdef ASSERT __ verify_frame_setup(); +#endif // jvmti support __ notify_method_entry(); diff --git a/src/hotspot/cpu/riscv/templateTable_riscv.cpp b/src/hotspot/cpu/riscv/templateTable_riscv.cpp index bd4a89d819967..2697b3e46dc14 100644 --- a/src/hotspot/cpu/riscv/templateTable_riscv.cpp +++ b/src/hotspot/cpu/riscv/templateTable_riscv.cpp @@ -133,7 +133,6 @@ Address TemplateTable::at_bcp(int offset) { void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg, Register temp_reg, bool load_bc_into_bc_reg /*=true*/, int byte_no) { - assert_different_registers(bc_reg, temp_reg); if (!RewriteBytecodes) { return; } Label L_patch_done; @@ -197,11 +196,7 @@ void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg, __ bind(L_okay); #endif - // Patch bytecode with release store to coordinate with ResolvedFieldEntry loads - // in fast bytecode codelets. load_field_entry has a memory barrier that gains - // the needed ordering, together with control dependency on entering the fast codelet - // itself. - __ membar(MacroAssembler::LoadStore | MacroAssembler::StoreStore); + // patch bytecode __ sb(bc_reg, at_bcp(0)); __ bind(L_patch_done); } @@ -3033,7 +3028,6 @@ void TemplateTable::fast_storefield(TosState state) { // X11: field offset, X12: field holder, X13: flags load_resolved_field_entry(x12, x12, noreg, x11, x13); - __ verify_field_offset(x11); { Label notVolatile; @@ -3121,8 +3115,6 @@ void TemplateTable::fast_accessfield(TosState state) { __ load_field_entry(x12, x11); __ load_sized_value(x11, Address(x12, in_bytes(ResolvedFieldEntry::field_offset_offset())), sizeof(int), true /*is_signed*/); - __ verify_field_offset(x11); - __ load_unsigned_byte(x13, Address(x12, in_bytes(ResolvedFieldEntry::flags_offset()))); // x10: object @@ -3178,9 +3170,7 @@ void TemplateTable::fast_xaccess(TosState state) { __ ld(x10, aaddress(0)); // access constant pool cache __ load_field_entry(x12, x13, 2); - __ load_sized_value(x11, Address(x12, in_bytes(ResolvedFieldEntry::field_offset_offset())), sizeof(int), true /*is_signed*/); - __ verify_field_offset(x11); // make sure exception is reported in correct bcp range (getfield is // next instruction) diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.cpp b/src/hotspot/cpu/riscv/vm_version_riscv.cpp index 6f4babc872ff1..9d6146a838907 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.cpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.cpp @@ -103,6 +103,17 @@ void VM_Version::common_initialize() { useRVA23U64Profile(); } + // Enable vendor specific features + + if (mvendorid.enabled()) { + // Rivos + if (mvendorid.value() == RIVOS) { + if (FLAG_IS_DEFAULT(UseConservativeFence)) { + FLAG_SET_DEFAULT(UseConservativeFence, false); + } + } + } + if (UseZic64b) { if (CacheLineSize != 64) { assert(!FLAG_IS_DEFAULT(CacheLineSize), "default cache line size should be 64 bytes"); @@ -188,7 +199,7 @@ void VM_Version::common_initialize() { FLAG_SET_DEFAULT(UsePopCountInstruction, false); } - if (UseZicboz && zicboz_block_size.value() > 0) { + 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); diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.hpp b/src/hotspot/cpu/riscv/vm_version_riscv.hpp index f74992cbc37a0..346ca35dc1ede 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.hpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.hpp @@ -52,19 +52,53 @@ class VM_Version : public Abstract_VM_Version { const char* const _pretty; const bool _feature_string; const uint64_t _linux_feature_bit; - + int64_t _value; public: RVFeatureValue(const char* pretty, int linux_bit_num, bool fstring) : - _pretty(pretty), _feature_string(fstring), _linux_feature_bit(nth_bit(linux_bit_num)) { + _pretty(pretty), _feature_string(fstring), _linux_feature_bit(nth_bit(linux_bit_num)), + _value(-1) { + } + virtual void enable_feature(int64_t value = 0) { + _value = value; + } + virtual void disable_feature() { + _value = -1; } - virtual void enable_feature(int64_t value = 0) = 0; - virtual void disable_feature() = 0; const char* pretty() { return _pretty; } uint64_t feature_bit() { return _linux_feature_bit; } bool feature_string() { return _feature_string; } + int64_t value() { return _value; } virtual bool enabled() = 0; virtual void update_flag() = 0; - virtual void log_enabled() = 0; + + protected: + bool deps_all_enabled(RVFeatureValue* dep0, ...) { + assert(dep0 != nullptr, "must not"); + + va_list va; + va_start(va, dep0); + RVFeatureValue* next = dep0; + bool enabled = true; + while (next != nullptr && enabled) { + enabled = next->enabled(); + next = va_arg(va, RVFeatureValue*); + } + va_end(va); + return enabled; + } + + void deps_string(stringStream& ss, RVFeatureValue* dep0, ...) { + assert(dep0 != nullptr, "must not"); + ss.print("%s (%s)", dep0->pretty(), dep0->enabled() ? "enabled" : "disabled"); + + va_list va; + va_start(va, dep0); + RVFeatureValue* next = nullptr; + while ((next = va_arg(va, RVFeatureValue*)) != nullptr) { + ss.print(", %s (%s)", next->pretty(), next->enabled() ? "enabled" : "disabled"); + } + va_end(va); + } }; #define UPDATE_DEFAULT(flag) \ @@ -83,9 +117,8 @@ class VM_Version : public Abstract_VM_Version { #define UPDATE_DEFAULT_DEP(flag, dep0, ...) \ void update_flag() { \ assert(enabled(), "Must be."); \ - DEBUG_ONLY(verify_deps(dep0, ##__VA_ARGS__)); \ if (FLAG_IS_DEFAULT(flag)) { \ - if (deps_all_enabled(dep0, ##__VA_ARGS__)) { \ + if (this->deps_all_enabled(dep0, ##__VA_ARGS__)) { \ FLAG_SET_DEFAULT(flag, true); \ } else { \ FLAG_SET_DEFAULT(flag, false); \ @@ -116,96 +149,40 @@ class VM_Version : public Abstract_VM_Version { class RVExtFeatureValue : public RVFeatureValue { const uint32_t _cpu_feature_index; - public: RVExtFeatureValue(const char* pretty, int linux_bit_num, uint32_t cpu_feature_index, bool fstring) : RVFeatureValue(pretty, linux_bit_num, fstring), _cpu_feature_index(cpu_feature_index) { } - int cpu_feature_index() { - // Can be used to check, for example, v is declared before Zvfh in RV_EXT_FEATURE_FLAGS. - return _cpu_feature_index; - } bool enabled() { return RVExtFeatures::current()->support_feature(_cpu_feature_index); } void enable_feature(int64_t value = 0) { + RVFeatureValue::enable_feature(value); RVExtFeatures::current()->set_feature(_cpu_feature_index); } void disable_feature() { + RVFeatureValue::disable_feature(); RVExtFeatures::current()->clear_feature(_cpu_feature_index); } - void log_enabled(); - - protected: - bool deps_all_enabled(RVExtFeatureValue* dep0, ...) { - assert(dep0 != nullptr, "must not"); - - va_list va; - va_start(va, dep0); - RVExtFeatureValue* next = dep0; - bool enabled = true; - while (next != nullptr && enabled) { - enabled = next->enabled(); - next = va_arg(va, RVExtFeatureValue*); - } - va_end(va); - return enabled; - } - - void deps_string(stringStream& ss, RVExtFeatureValue* dep0, ...) { - assert(dep0 != nullptr, "must not"); - ss.print("%s (%s)", dep0->pretty(), dep0->enabled() ? "enabled" : "disabled"); - - va_list va; - va_start(va, dep0); - RVExtFeatureValue* next = nullptr; - while ((next = va_arg(va, RVExtFeatureValue*)) != nullptr) { - ss.print(", %s (%s)", next->pretty(), next->enabled() ? "enabled" : "disabled"); - } - va_end(va); - } - -#ifdef ASSERT - void verify_deps(RVExtFeatureValue* dep0, ...) { - assert(dep0 != nullptr, "must not"); - assert(cpu_feature_index() >= 0, "must"); - - va_list va; - va_start(va, dep0); - RVExtFeatureValue* next = dep0; - while (next != nullptr) { - assert(next->cpu_feature_index() >= 0, "must"); - // We only need to check depenency relationship for extension flags. - // The dependant ones must be declared before this, for example, v must be declared - // before Zvfh in RV_EXT_FEATURE_FLAGS. The reason is in setup_cpu_available_features - // we need to make sure v is `update_flag`ed before Zvfh, so Zvfh is `update_flag`ed - // based on v. - assert(cpu_feature_index() > next->cpu_feature_index(), "Invalid"); - next = va_arg(va, RVExtFeatureValue*); - } - va_end(va); - } -#endif // ASSERT }; class RVNonExtFeatureValue : public RVFeatureValue { - static const int64_t DEFAULT_VALUE = -1; - int64_t _value; - + bool _enabled; public: RVNonExtFeatureValue(const char* pretty, int linux_bit_num, bool fstring) : RVFeatureValue(pretty, linux_bit_num, fstring), - _value(DEFAULT_VALUE) { + _enabled(false) { } - bool enabled() { return _value != DEFAULT_VALUE; } - void enable_feature(int64_t value) { - assert(value != DEFAULT_VALUE, "Sanity"); - _value = value; + bool enabled() { return _enabled; } + void enable_feature(int64_t value = 0) { + RVFeatureValue::enable_feature(value); + _enabled = true; + } + void disable_feature() { + RVFeatureValue::disable_feature(); + _enabled = false; } - void disable_feature() { _value = DEFAULT_VALUE; } - int64_t value() { return _value; } - void log_enabled(); }; public: @@ -305,14 +282,14 @@ class VM_Version : public Abstract_VM_Version { decl(marchid , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ /* A unique encoding of the version of the processor implementation. */ \ decl(mimpid , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ - /* Manufactory JEDEC id encoded, ISA vol 2 3.1.2.. */ \ - decl(mvendorid , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ /* SATP bits (number of virtual addr bits) mbare, sv39, sv48, sv57, sv64 */ \ decl(satp_mode , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ /* Performance of misaligned scalar accesses (unknown, emulated, slow, fast, unsupported) */ \ decl(unaligned_scalar , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ /* Performance of misaligned vector accesses (unknown, unspported, slow, fast) */ \ decl(unaligned_vector , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ + /* Manufactory JEDEC id encoded, ISA vol 2 3.1.2.. */ \ + decl(mvendorid , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ decl(zicboz_block_size , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ #define DECLARE_RV_NON_EXT_FEATURE(PRETTY, LINUX_BIT, FSTRING, FLAGF) \ diff --git a/src/hotspot/cpu/s390/gc/g1/g1_s390.ad b/src/hotspot/cpu/s390/gc/g1/g1_s390.ad index 000ac3bc5ba5b..7aed374fdaebd 100644 --- a/src/hotspot/cpu/s390/gc/g1/g1_s390.ad +++ b/src/hotspot/cpu/s390/gc/g1/g1_s390.ad @@ -356,7 +356,7 @@ instruct g1CompareAndExchangeP(iRegP mem_ptr, rarg5RegP oldval, iRegP_N2P newval __ z_lgr($res$$Register, $oldval$$Register); // previous content - __ z_csg($res$$Register, $newval$$Register, 0, $mem_ptr$$reg); + __ z_csg($oldval$$Register, $newval$$Register, 0, $mem_ptr$$reg); write_barrier_post(masm, this, $mem_ptr$$Register /* store_addr */, diff --git a/src/hotspot/cpu/s390/javaFrameAnchor_s390.hpp b/src/hotspot/cpu/s390/javaFrameAnchor_s390.hpp index 307034ca0cd5d..ae8b8766159c6 100644 --- a/src/hotspot/cpu/s390/javaFrameAnchor_s390.hpp +++ b/src/hotspot/cpu/s390/javaFrameAnchor_s390.hpp @@ -35,32 +35,38 @@ // 3 - restoring an old state (javaCalls). inline void clear(void) { - // No hardware barriers are necessary. All members are volatile and the profiler - // is run from a signal handler and only observers the thread its running on. - // Clearing _last_Java_sp must be first. - + OrderAccess::release(); _last_Java_sp = nullptr; + // Fence? + OrderAccess::fence(); _last_Java_pc = nullptr; } inline void set(intptr_t* sp, address pc) { _last_Java_pc = pc; + + OrderAccess::release(); _last_Java_sp = sp; } void copy(JavaFrameAnchor* src) { - // No hardware barriers are necessary. All members are volatile and the profiler - // is run from a signal handler and only observers the thread its running on. - + // In order to make sure the transition state is valid for "this" // we must clear _last_Java_sp before copying the rest of the new data. + // Hack Alert: Temporary bugfix for 4717480/4721647 + // To act like previous version (pd_cache_state) don't null _last_Java_sp + // unless the value is changing. + // if (_last_Java_sp != src->_last_Java_sp) { + OrderAccess::release(); _last_Java_sp = nullptr; + OrderAccess::fence(); } _last_Java_pc = src->_last_Java_pc; // Must be last so profiler will always see valid frame if has_last_frame() is true. + OrderAccess::release(); _last_Java_sp = src->_last_Java_sp; } @@ -74,7 +80,7 @@ intptr_t* last_Java_fp(void) { return nullptr; } intptr_t* last_Java_sp() const { return _last_Java_sp; } - void set_last_Java_sp(intptr_t* sp) { _last_Java_sp = sp; } + void set_last_Java_sp(intptr_t* sp) { OrderAccess::release(); _last_Java_sp = sp; } address last_Java_pc(void) { return _last_Java_pc; } diff --git a/src/hotspot/cpu/s390/s390.ad b/src/hotspot/cpu/s390/s390.ad index ab991896b53d8..cfc8b19534b59 100644 --- a/src/hotspot/cpu/s390/s390.ad +++ b/src/hotspot/cpu/s390/s390.ad @@ -1961,22 +1961,22 @@ bool Matcher::use_asm_for_ldiv_by_con(jlong divisor) { } // Register for DIVI projection of divmodI -const RegMask& Matcher::divI_proj_mask() { +RegMask Matcher::divI_proj_mask() { return _Z_RARG4_INT_REG_mask; } // Register for MODI projection of divmodI -const RegMask& Matcher::modI_proj_mask() { +RegMask Matcher::modI_proj_mask() { return _Z_RARG3_INT_REG_mask; } // Register for DIVL projection of divmodL -const RegMask& Matcher::divL_proj_mask() { +RegMask Matcher::divL_proj_mask() { return _Z_RARG4_LONG_REG_mask; } // Register for MODL projection of divmodL -const RegMask& Matcher::modL_proj_mask() { +RegMask Matcher::modL_proj_mask() { return _Z_RARG3_LONG_REG_mask; } diff --git a/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp b/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp index 09c5d93dbb3a2..925444792caac 100644 --- a/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/gc/shared/barrierSetAssembler_x86.cpp @@ -471,33 +471,33 @@ void SaveLiveRegisters::initialize(BarrierStubC2* stub) { // Create mask of caller saved registers that need to // be saved/restored if live RegMask caller_saved; - caller_saved.insert(OptoReg::as_OptoReg(rax->as_VMReg())); - caller_saved.insert(OptoReg::as_OptoReg(rcx->as_VMReg())); - caller_saved.insert(OptoReg::as_OptoReg(rdx->as_VMReg())); - caller_saved.insert(OptoReg::as_OptoReg(rsi->as_VMReg())); - caller_saved.insert(OptoReg::as_OptoReg(rdi->as_VMReg())); - caller_saved.insert(OptoReg::as_OptoReg(r8->as_VMReg())); - caller_saved.insert(OptoReg::as_OptoReg(r9->as_VMReg())); - caller_saved.insert(OptoReg::as_OptoReg(r10->as_VMReg())); - caller_saved.insert(OptoReg::as_OptoReg(r11->as_VMReg())); + caller_saved.Insert(OptoReg::as_OptoReg(rax->as_VMReg())); + caller_saved.Insert(OptoReg::as_OptoReg(rcx->as_VMReg())); + caller_saved.Insert(OptoReg::as_OptoReg(rdx->as_VMReg())); + caller_saved.Insert(OptoReg::as_OptoReg(rsi->as_VMReg())); + caller_saved.Insert(OptoReg::as_OptoReg(rdi->as_VMReg())); + caller_saved.Insert(OptoReg::as_OptoReg(r8->as_VMReg())); + caller_saved.Insert(OptoReg::as_OptoReg(r9->as_VMReg())); + caller_saved.Insert(OptoReg::as_OptoReg(r10->as_VMReg())); + caller_saved.Insert(OptoReg::as_OptoReg(r11->as_VMReg())); if (UseAPX) { - caller_saved.insert(OptoReg::as_OptoReg(r16->as_VMReg())); - caller_saved.insert(OptoReg::as_OptoReg(r17->as_VMReg())); - caller_saved.insert(OptoReg::as_OptoReg(r18->as_VMReg())); - caller_saved.insert(OptoReg::as_OptoReg(r19->as_VMReg())); - caller_saved.insert(OptoReg::as_OptoReg(r20->as_VMReg())); - caller_saved.insert(OptoReg::as_OptoReg(r21->as_VMReg())); - caller_saved.insert(OptoReg::as_OptoReg(r22->as_VMReg())); - caller_saved.insert(OptoReg::as_OptoReg(r23->as_VMReg())); - caller_saved.insert(OptoReg::as_OptoReg(r24->as_VMReg())); - caller_saved.insert(OptoReg::as_OptoReg(r25->as_VMReg())); - caller_saved.insert(OptoReg::as_OptoReg(r26->as_VMReg())); - caller_saved.insert(OptoReg::as_OptoReg(r27->as_VMReg())); - caller_saved.insert(OptoReg::as_OptoReg(r28->as_VMReg())); - caller_saved.insert(OptoReg::as_OptoReg(r29->as_VMReg())); - caller_saved.insert(OptoReg::as_OptoReg(r30->as_VMReg())); - caller_saved.insert(OptoReg::as_OptoReg(r31->as_VMReg())); + caller_saved.Insert(OptoReg::as_OptoReg(r16->as_VMReg())); + caller_saved.Insert(OptoReg::as_OptoReg(r17->as_VMReg())); + caller_saved.Insert(OptoReg::as_OptoReg(r18->as_VMReg())); + caller_saved.Insert(OptoReg::as_OptoReg(r19->as_VMReg())); + caller_saved.Insert(OptoReg::as_OptoReg(r20->as_VMReg())); + caller_saved.Insert(OptoReg::as_OptoReg(r21->as_VMReg())); + caller_saved.Insert(OptoReg::as_OptoReg(r22->as_VMReg())); + caller_saved.Insert(OptoReg::as_OptoReg(r23->as_VMReg())); + caller_saved.Insert(OptoReg::as_OptoReg(r24->as_VMReg())); + caller_saved.Insert(OptoReg::as_OptoReg(r25->as_VMReg())); + caller_saved.Insert(OptoReg::as_OptoReg(r26->as_VMReg())); + caller_saved.Insert(OptoReg::as_OptoReg(r27->as_VMReg())); + caller_saved.Insert(OptoReg::as_OptoReg(r28->as_VMReg())); + caller_saved.Insert(OptoReg::as_OptoReg(r29->as_VMReg())); + caller_saved.Insert(OptoReg::as_OptoReg(r30->as_VMReg())); + caller_saved.Insert(OptoReg::as_OptoReg(r31->as_VMReg())); } int gp_spill_size = 0; @@ -511,7 +511,7 @@ void SaveLiveRegisters::initialize(BarrierStubC2* stub) { const VMReg vm_reg = OptoReg::as_VMReg(opto_reg); if (vm_reg->is_Register()) { - if (caller_saved.member(opto_reg)) { + if (caller_saved.Member(opto_reg)) { _gp_registers.append(vm_reg->as_Register()); gp_spill_size += 8; } diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad index 62306b562d6d4..b40f9e2924a97 100644 --- a/src/hotspot/cpu/x86/x86_64.ad +++ b/src/hotspot/cpu/x86/x86_64.ad @@ -497,96 +497,96 @@ void reg_mask_init() { // _ALL_REG_mask is generated by adlc from the all_reg register class below. // We derive a number of subsets from it. - _ANY_REG_mask.assignFrom(_ALL_REG_mask); + _ANY_REG_mask = _ALL_REG_mask; if (PreserveFramePointer) { - _ANY_REG_mask.remove(OptoReg::as_OptoReg(rbp->as_VMReg())); - _ANY_REG_mask.remove(OptoReg::as_OptoReg(rbp->as_VMReg()->next())); + _ANY_REG_mask.Remove(OptoReg::as_OptoReg(rbp->as_VMReg())); + _ANY_REG_mask.Remove(OptoReg::as_OptoReg(rbp->as_VMReg()->next())); } if (need_r12_heapbase()) { - _ANY_REG_mask.remove(OptoReg::as_OptoReg(r12->as_VMReg())); - _ANY_REG_mask.remove(OptoReg::as_OptoReg(r12->as_VMReg()->next())); + _ANY_REG_mask.Remove(OptoReg::as_OptoReg(r12->as_VMReg())); + _ANY_REG_mask.Remove(OptoReg::as_OptoReg(r12->as_VMReg()->next())); } - _PTR_REG_mask.assignFrom(_ANY_REG_mask); - _PTR_REG_mask.remove(OptoReg::as_OptoReg(rsp->as_VMReg())); - _PTR_REG_mask.remove(OptoReg::as_OptoReg(rsp->as_VMReg()->next())); - _PTR_REG_mask.remove(OptoReg::as_OptoReg(r15->as_VMReg())); - _PTR_REG_mask.remove(OptoReg::as_OptoReg(r15->as_VMReg()->next())); + _PTR_REG_mask = _ANY_REG_mask; + _PTR_REG_mask.Remove(OptoReg::as_OptoReg(rsp->as_VMReg())); + _PTR_REG_mask.Remove(OptoReg::as_OptoReg(rsp->as_VMReg()->next())); + _PTR_REG_mask.Remove(OptoReg::as_OptoReg(r15->as_VMReg())); + _PTR_REG_mask.Remove(OptoReg::as_OptoReg(r15->as_VMReg()->next())); if (!UseAPX) { for (uint i = 0; i < sizeof(egprs)/sizeof(Register); i++) { - _PTR_REG_mask.remove(OptoReg::as_OptoReg(egprs[i]->as_VMReg())); - _PTR_REG_mask.remove(OptoReg::as_OptoReg(egprs[i]->as_VMReg()->next())); + _PTR_REG_mask.Remove(OptoReg::as_OptoReg(egprs[i]->as_VMReg())); + _PTR_REG_mask.Remove(OptoReg::as_OptoReg(egprs[i]->as_VMReg()->next())); } } - _STACK_OR_PTR_REG_mask.assignFrom(_PTR_REG_mask); - _STACK_OR_PTR_REG_mask.or_with(STACK_OR_STACK_SLOTS_mask()); + _STACK_OR_PTR_REG_mask = _PTR_REG_mask; + _STACK_OR_PTR_REG_mask.OR(STACK_OR_STACK_SLOTS_mask()); - _PTR_REG_NO_RBP_mask.assignFrom(_PTR_REG_mask); - _PTR_REG_NO_RBP_mask.remove(OptoReg::as_OptoReg(rbp->as_VMReg())); - _PTR_REG_NO_RBP_mask.remove(OptoReg::as_OptoReg(rbp->as_VMReg()->next())); + _PTR_REG_NO_RBP_mask = _PTR_REG_mask; + _PTR_REG_NO_RBP_mask.Remove(OptoReg::as_OptoReg(rbp->as_VMReg())); + _PTR_REG_NO_RBP_mask.Remove(OptoReg::as_OptoReg(rbp->as_VMReg()->next())); - _PTR_NO_RAX_REG_mask.assignFrom(_PTR_REG_mask); - _PTR_NO_RAX_REG_mask.remove(OptoReg::as_OptoReg(rax->as_VMReg())); - _PTR_NO_RAX_REG_mask.remove(OptoReg::as_OptoReg(rax->as_VMReg()->next())); + _PTR_NO_RAX_REG_mask = _PTR_REG_mask; + _PTR_NO_RAX_REG_mask.Remove(OptoReg::as_OptoReg(rax->as_VMReg())); + _PTR_NO_RAX_REG_mask.Remove(OptoReg::as_OptoReg(rax->as_VMReg()->next())); - _PTR_NO_RAX_RBX_REG_mask.assignFrom(_PTR_NO_RAX_REG_mask); - _PTR_NO_RAX_RBX_REG_mask.remove(OptoReg::as_OptoReg(rbx->as_VMReg())); - _PTR_NO_RAX_RBX_REG_mask.remove(OptoReg::as_OptoReg(rbx->as_VMReg()->next())); + _PTR_NO_RAX_RBX_REG_mask = _PTR_NO_RAX_REG_mask; + _PTR_NO_RAX_RBX_REG_mask.Remove(OptoReg::as_OptoReg(rbx->as_VMReg())); + _PTR_NO_RAX_RBX_REG_mask.Remove(OptoReg::as_OptoReg(rbx->as_VMReg()->next())); - _LONG_REG_mask.assignFrom(_PTR_REG_mask); - _STACK_OR_LONG_REG_mask.assignFrom(_LONG_REG_mask); - _STACK_OR_LONG_REG_mask.or_with(STACK_OR_STACK_SLOTS_mask()); + _LONG_REG_mask = _PTR_REG_mask; + _STACK_OR_LONG_REG_mask = _LONG_REG_mask; + _STACK_OR_LONG_REG_mask.OR(STACK_OR_STACK_SLOTS_mask()); - _LONG_NO_RAX_RDX_REG_mask.assignFrom(_LONG_REG_mask); - _LONG_NO_RAX_RDX_REG_mask.remove(OptoReg::as_OptoReg(rax->as_VMReg())); - _LONG_NO_RAX_RDX_REG_mask.remove(OptoReg::as_OptoReg(rax->as_VMReg()->next())); - _LONG_NO_RAX_RDX_REG_mask.remove(OptoReg::as_OptoReg(rdx->as_VMReg())); - _LONG_NO_RAX_RDX_REG_mask.remove(OptoReg::as_OptoReg(rdx->as_VMReg()->next())); + _LONG_NO_RAX_RDX_REG_mask = _LONG_REG_mask; + _LONG_NO_RAX_RDX_REG_mask.Remove(OptoReg::as_OptoReg(rax->as_VMReg())); + _LONG_NO_RAX_RDX_REG_mask.Remove(OptoReg::as_OptoReg(rax->as_VMReg()->next())); + _LONG_NO_RAX_RDX_REG_mask.Remove(OptoReg::as_OptoReg(rdx->as_VMReg())); + _LONG_NO_RAX_RDX_REG_mask.Remove(OptoReg::as_OptoReg(rdx->as_VMReg()->next())); - _LONG_NO_RCX_REG_mask.assignFrom(_LONG_REG_mask); - _LONG_NO_RCX_REG_mask.remove(OptoReg::as_OptoReg(rcx->as_VMReg())); - _LONG_NO_RCX_REG_mask.remove(OptoReg::as_OptoReg(rcx->as_VMReg()->next())); + _LONG_NO_RCX_REG_mask = _LONG_REG_mask; + _LONG_NO_RCX_REG_mask.Remove(OptoReg::as_OptoReg(rcx->as_VMReg())); + _LONG_NO_RCX_REG_mask.Remove(OptoReg::as_OptoReg(rcx->as_VMReg()->next())); - _LONG_NO_RBP_R13_REG_mask.assignFrom(_LONG_REG_mask); - _LONG_NO_RBP_R13_REG_mask.remove(OptoReg::as_OptoReg(rbp->as_VMReg())); - _LONG_NO_RBP_R13_REG_mask.remove(OptoReg::as_OptoReg(rbp->as_VMReg()->next())); - _LONG_NO_RBP_R13_REG_mask.remove(OptoReg::as_OptoReg(r13->as_VMReg())); - _LONG_NO_RBP_R13_REG_mask.remove(OptoReg::as_OptoReg(r13->as_VMReg()->next())); + _LONG_NO_RBP_R13_REG_mask = _LONG_REG_mask; + _LONG_NO_RBP_R13_REG_mask.Remove(OptoReg::as_OptoReg(rbp->as_VMReg())); + _LONG_NO_RBP_R13_REG_mask.Remove(OptoReg::as_OptoReg(rbp->as_VMReg()->next())); + _LONG_NO_RBP_R13_REG_mask.Remove(OptoReg::as_OptoReg(r13->as_VMReg())); + _LONG_NO_RBP_R13_REG_mask.Remove(OptoReg::as_OptoReg(r13->as_VMReg()->next())); - _INT_REG_mask.assignFrom(_ALL_INT_REG_mask); + _INT_REG_mask = _ALL_INT_REG_mask; if (!UseAPX) { for (uint i = 0; i < sizeof(egprs)/sizeof(Register); i++) { - _INT_REG_mask.remove(OptoReg::as_OptoReg(egprs[i]->as_VMReg())); + _INT_REG_mask.Remove(OptoReg::as_OptoReg(egprs[i]->as_VMReg())); } } if (PreserveFramePointer) { - _INT_REG_mask.remove(OptoReg::as_OptoReg(rbp->as_VMReg())); + _INT_REG_mask.Remove(OptoReg::as_OptoReg(rbp->as_VMReg())); } if (need_r12_heapbase()) { - _INT_REG_mask.remove(OptoReg::as_OptoReg(r12->as_VMReg())); + _INT_REG_mask.Remove(OptoReg::as_OptoReg(r12->as_VMReg())); } - _STACK_OR_INT_REG_mask.assignFrom(_INT_REG_mask); - _STACK_OR_INT_REG_mask.or_with(STACK_OR_STACK_SLOTS_mask()); + _STACK_OR_INT_REG_mask = _INT_REG_mask; + _STACK_OR_INT_REG_mask.OR(STACK_OR_STACK_SLOTS_mask()); - _INT_NO_RAX_RDX_REG_mask.assignFrom(_INT_REG_mask); - _INT_NO_RAX_RDX_REG_mask.remove(OptoReg::as_OptoReg(rax->as_VMReg())); - _INT_NO_RAX_RDX_REG_mask.remove(OptoReg::as_OptoReg(rdx->as_VMReg())); + _INT_NO_RAX_RDX_REG_mask = _INT_REG_mask; + _INT_NO_RAX_RDX_REG_mask.Remove(OptoReg::as_OptoReg(rax->as_VMReg())); + _INT_NO_RAX_RDX_REG_mask.Remove(OptoReg::as_OptoReg(rdx->as_VMReg())); - _INT_NO_RCX_REG_mask.assignFrom(_INT_REG_mask); - _INT_NO_RCX_REG_mask.remove(OptoReg::as_OptoReg(rcx->as_VMReg())); + _INT_NO_RCX_REG_mask = _INT_REG_mask; + _INT_NO_RCX_REG_mask.Remove(OptoReg::as_OptoReg(rcx->as_VMReg())); - _INT_NO_RBP_R13_REG_mask.assignFrom(_INT_REG_mask); - _INT_NO_RBP_R13_REG_mask.remove(OptoReg::as_OptoReg(rbp->as_VMReg())); - _INT_NO_RBP_R13_REG_mask.remove(OptoReg::as_OptoReg(r13->as_VMReg())); + _INT_NO_RBP_R13_REG_mask = _INT_REG_mask; + _INT_NO_RBP_R13_REG_mask.Remove(OptoReg::as_OptoReg(rbp->as_VMReg())); + _INT_NO_RBP_R13_REG_mask.Remove(OptoReg::as_OptoReg(r13->as_VMReg())); // _FLOAT_REG_LEGACY_mask/_FLOAT_REG_EVEX_mask is generated by adlc // from the float_reg_legacy/float_reg_evex register class. - _FLOAT_REG_mask.assignFrom(VM_Version::supports_evex() ? _FLOAT_REG_EVEX_mask : _FLOAT_REG_LEGACY_mask); + _FLOAT_REG_mask = VM_Version::supports_evex() ? _FLOAT_REG_EVEX_mask : _FLOAT_REG_LEGACY_mask; } static bool generate_vzeroupper(Compile* C) { @@ -756,7 +756,7 @@ static void emit_fp_min_max(MacroAssembler* masm, XMMRegister dst, } //============================================================================= -const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::EMPTY; +const RegMask& MachConstantBaseNode::_out_RegMask = RegMask::Empty; int ConstantTable::calculate_table_base_offset() const { return 0; // absolute addressing, no offset @@ -1658,7 +1658,7 @@ bool Matcher::is_spillable_arg(int reg) uint Matcher::int_pressure_limit() { - return (INTPRESSURE == -1) ? _INT_REG_mask.size() : INTPRESSURE; + return (INTPRESSURE == -1) ? _INT_REG_mask.Size() : INTPRESSURE; } uint Matcher::float_pressure_limit() @@ -1666,7 +1666,7 @@ uint Matcher::float_pressure_limit() // After experiment around with different values, the following default threshold // works best for LCM's register pressure scheduling on x64. uint dec_count = VM_Version::supports_evex() ? 4 : 2; - uint default_float_pressure_threshold = _FLOAT_REG_mask.size() - dec_count; + uint default_float_pressure_threshold = _FLOAT_REG_mask.Size() - dec_count; return (FLOATPRESSURE == -1) ? default_float_pressure_threshold : FLOATPRESSURE; } @@ -1678,22 +1678,22 @@ bool Matcher::use_asm_for_ldiv_by_con( jlong divisor ) { } // Register for DIVI projection of divmodI -const RegMask& Matcher::divI_proj_mask() { +RegMask Matcher::divI_proj_mask() { return INT_RAX_REG_mask(); } // Register for MODI projection of divmodI -const RegMask& Matcher::modI_proj_mask() { +RegMask Matcher::modI_proj_mask() { return INT_RDX_REG_mask(); } // Register for DIVL projection of divmodL -const RegMask& Matcher::divL_proj_mask() { +RegMask Matcher::divL_proj_mask() { return LONG_RAX_REG_mask(); } // Register for MODL projection of divmodL -const RegMask& Matcher::modL_proj_mask() { +RegMask Matcher::modL_proj_mask() { return LONG_RDX_REG_mask(); } diff --git a/src/hotspot/os/bsd/gc/z/zNUMA_bsd.cpp b/src/hotspot/os/bsd/gc/z/zNUMA_bsd.cpp index 3acaa9ab8f94f..d0c06e2ebf1bc 100644 --- a/src/hotspot/os/bsd/gc/z/zNUMA_bsd.cpp +++ b/src/hotspot/os/bsd/gc/z/zNUMA_bsd.cpp @@ -46,7 +46,3 @@ uint32_t ZNUMA::memory_id(uintptr_t addr) { // NUMA support not enabled, assume everything belongs to node zero return 0; } - -int ZNUMA::numa_id_to_node(uint32_t numa_id) { - ShouldNotCallThis(); -} diff --git a/src/hotspot/os/linux/gc/z/zNUMA_linux.cpp b/src/hotspot/os/linux/gc/z/zNUMA_linux.cpp index ab7498b313c5b..74e696559401f 100644 --- a/src/hotspot/os/linux/gc/z/zNUMA_linux.cpp +++ b/src/hotspot/os/linux/gc/z/zNUMA_linux.cpp @@ -32,35 +32,12 @@ #include "runtime/os.hpp" #include "utilities/debug.hpp" -static uint* z_numa_id_to_node = nullptr; -static uint32_t* z_node_to_numa_id = nullptr; - void ZNUMA::pd_initialize() { _enabled = UseNUMA; - size_t configured_nodes = 0; - - if (UseNUMA) { - const size_t max_nodes = os::Linux::numa_num_configured_nodes(); - z_numa_id_to_node = NEW_C_HEAP_ARRAY(uint, max_nodes, mtGC); - configured_nodes = os::numa_get_leaf_groups(z_numa_id_to_node, 0); - - z_node_to_numa_id = NEW_C_HEAP_ARRAY(uint32_t, max_nodes, mtGC); - - // Fill the array with invalid NUMA ids - for (uint32_t i = 0; i < max_nodes; i++) { - z_node_to_numa_id[i] = (uint32_t)-1; - } - - // Fill the reverse mappings - for (uint32_t i = 0; i < configured_nodes; i++) { - z_node_to_numa_id[z_numa_id_to_node[i]] = i; - } - } - // UseNUMA and is_faked() are mutually excluded in zArguments.cpp. _count = UseNUMA - ? configured_nodes + ? os::Linux::numa_max_node() + 1 : !FLAG_IS_DEFAULT(ZFakeNUMA) ? ZFakeNUMA : 1; // No NUMA nodes @@ -77,7 +54,7 @@ uint32_t ZNUMA::id() { return 0; } - return z_node_to_numa_id[os::Linux::get_node_by_cpu(ZCPU::id())]; + return os::Linux::get_node_by_cpu(ZCPU::id()); } uint32_t ZNUMA::memory_id(uintptr_t addr) { @@ -86,21 +63,14 @@ uint32_t ZNUMA::memory_id(uintptr_t addr) { return 0; } - int node = -1; + uint32_t id = (uint32_t)-1; - if (ZSyscall::get_mempolicy(&node, nullptr, 0, (void*)addr, MPOL_F_NODE | MPOL_F_ADDR) == -1) { + if (ZSyscall::get_mempolicy((int*)&id, nullptr, 0, (void*)addr, MPOL_F_NODE | MPOL_F_ADDR) == -1) { ZErrno err; fatal("Failed to get NUMA id for memory at " PTR_FORMAT " (%s)", addr, err.to_string()); } - DEBUG_ONLY(const int max_nodes = os::Linux::numa_num_configured_nodes();) - assert(node < max_nodes, "NUMA node is out of bounds node=%d, max=%d", node, max_nodes); - - return z_node_to_numa_id[node]; -} - -int ZNUMA::numa_id_to_node(uint32_t numa_id) { - assert(numa_id < _count, "NUMA id out of range 0 <= %ud <= %ud", numa_id, _count); + assert(id < _count, "Invalid NUMA id"); - return (int)z_numa_id_to_node[numa_id]; + return id; } diff --git a/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.cpp b/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.cpp index 25ffd0b8078e4..84dfcbd6614eb 100644 --- a/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.cpp +++ b/src/hotspot/os/linux/gc/z/zPhysicalMemoryBacking_linux.cpp @@ -629,7 +629,7 @@ bool ZPhysicalMemoryBacking::commit_inner(zbacking_offset offset, size_t length) size_t ZPhysicalMemoryBacking::commit_numa_preferred(zbacking_offset offset, size_t length, uint32_t numa_id) const { // Setup NUMA policy to allocate memory from a preferred node - os::Linux::numa_set_preferred(ZNUMA::numa_id_to_node(numa_id)); + os::Linux::numa_set_preferred((int)numa_id); const size_t committed = commit_default(offset, length); diff --git a/src/hotspot/os/posix/perfMemory_posix.cpp b/src/hotspot/os/posix/perfMemory_posix.cpp index 2cc0263d2913b..ed83487265cb0 100644 --- a/src/hotspot/os/posix/perfMemory_posix.cpp +++ b/src/hotspot/os/posix/perfMemory_posix.cpp @@ -26,7 +26,6 @@ #include "classfile/vmSymbols.hpp" #include "jvm_io.h" #include "logging/log.hpp" -#include "logging/logStream.hpp" #include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" #include "nmt/memTracker.hpp" @@ -72,7 +71,9 @@ static char* create_standard_memory(size_t size) { // commit memory if (!os::commit_memory(mapAddress, size, !ExecMem)) { - log_debug(perf)("could not commit PerfData memory"); + if (PrintMiscellaneous && Verbose) { + warning("Could not commit PerfData memory\n"); + } os::release_memory(mapAddress, size); return nullptr; } @@ -296,12 +297,11 @@ static DIR *open_directory_secure(const char* dirname) { RESTARTABLE(::open(dirname, O_RDONLY|O_NOFOLLOW), result); if (result == OS_ERR) { // Directory doesn't exist or is a symlink, so there is nothing to cleanup. - if (log_is_enabled(Debug, perf)) { - LogStreamHandle(Debug, perf) log; + if (PrintMiscellaneous && Verbose) { if (errno == ELOOP) { - log.print_cr("directory %s is a symlink and is not secure", dirname); + warning("directory %s is a symlink and is not secure\n", dirname); } else { - log.print_cr("could not open directory %s: %s", dirname, os::strerror(errno)); + warning("could not open directory %s: %s\n", dirname, os::strerror(errno)); } } return dirp; @@ -371,7 +371,9 @@ static DIR *open_directory_secure_cwd(const char* dirname, int *saved_cwd_fd) { // handle errors, otherwise shared memory files will be created in cwd. result = fchdir(fd); if (result == OS_ERR) { - log_debug(perf)("could not change to directory %s", dirname); + if (PrintMiscellaneous && Verbose) { + warning("could not change to directory %s", dirname); + } if (*saved_cwd_fd != -1) { ::close(*saved_cwd_fd); *saved_cwd_fd = -1; @@ -409,12 +411,16 @@ static bool is_file_secure(int fd, const char *filename) { // Determine if the file is secure. RESTARTABLE(::fstat(fd, &statbuf), result); if (result == OS_ERR) { - log_debug(perf)("fstat failed on %s: %s", filename, os::strerror(errno)); + if (PrintMiscellaneous && Verbose) { + warning("fstat failed on %s: %s\n", filename, os::strerror(errno)); + } return false; } if (statbuf.st_nlink > 1) { // A file with multiple links is not expected. - log_debug(perf)("file %s has multiple links", filename); + if (PrintMiscellaneous && Verbose) { + warning("file %s has multiple links\n", filename); + } return false; } return true; @@ -441,10 +447,10 @@ static char* get_user_name(uid_t uid) { int result = getpwuid_r(uid, &pwent, pwbuf, (size_t)bufsize, &p); if (result != 0 || p == nullptr || p->pw_name == nullptr || *(p->pw_name) == '\0') { - if (log_is_enabled(Debug, perf)) { - LogStreamHandle(Debug, perf) log; + if (PrintMiscellaneous && Verbose) { if (result != 0) { - log.print_cr("Could not retrieve passwd entry: %s", os::strerror(result)); + warning("Could not retrieve passwd entry: %s\n", + os::strerror(result)); } else if (p == nullptr) { // this check is added to protect against an observed problem @@ -457,11 +463,13 @@ static char* get_user_name(uid_t uid) { // message may result in an erroneous message. // Bug Id 89052 was opened with RedHat. // - log.print_cr("Could not retrieve passwd entry: %s", os::strerror(errno)); + warning("Could not retrieve passwd entry: %s\n", + os::strerror(errno)); } else { - log.print_cr("Could not determine user name: %s", - p->pw_name == nullptr ? "pw_name = null" : "pw_name zero length"); + warning("Could not determine user name: %s\n", + p->pw_name == nullptr ? "pw_name = null" : + "pw_name zero length"); } } FREE_C_HEAP_ARRAY(char, pwbuf); @@ -672,10 +680,10 @@ static void remove_file(const char* path) { // maliciously planted, the directory's presence won't hurt anything. // RESTARTABLE(::unlink(path), result); - if (log_is_enabled(Debug, perf) && result == OS_ERR) { + if (PrintMiscellaneous && Verbose && result == OS_ERR) { if (errno != ENOENT) { - log_debug(perf)("could not unlink shared memory backing store file %s : %s", - path, os::strerror(errno)); + warning("Could not unlink shared memory backing" + " store file %s : %s\n", path, os::strerror(errno)); } } } @@ -811,16 +819,23 @@ static bool make_user_tmp_dir(const char* dirname) { // The directory already exists and was probably created by another // JVM instance. However, this could also be the result of a // deliberate symlink. Verify that the existing directory is safe. + // if (!is_directory_secure(dirname)) { // directory is not secure - log_debug(perf)("%s directory is insecure", dirname); + if (PrintMiscellaneous && Verbose) { + warning("%s directory is insecure\n", dirname); + } return false; } } else { // we encountered some other failure while attempting // to create the directory - log_debug(perf)("could not create directory %s: %s", dirname, os::strerror(errno)); + // + if (PrintMiscellaneous && Verbose) { + warning("could not create directory %s: %s\n", + dirname, os::strerror(errno)); + } return false; } } @@ -857,12 +872,11 @@ static int create_sharedmem_file(const char* dirname, const char* filename, size int fd; RESTARTABLE(os::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IRUSR|S_IWUSR), fd); if (fd == OS_ERR) { - if (log_is_enabled(Debug, perf)) { - LogStreamHandle(Debug, perf) log; + if (PrintMiscellaneous && Verbose) { if (errno == ELOOP) { - log.print_cr("file %s is a symlink and is not secure", filename); + warning("file %s is a symlink and is not secure\n", filename); } else { - log.print_cr("could not create file %s: %s", filename, os::strerror(errno)); + warning("could not create file %s: %s\n", filename, os::strerror(errno)); } } // close the directory and reset the current working directory @@ -910,14 +924,18 @@ static int create_sharedmem_file(const char* dirname, const char* filename, size // truncate the file to get rid of any existing data RESTARTABLE(::ftruncate(fd, (off_t)0), result); if (result == OS_ERR) { - log_debug(perf)("could not truncate shared memory file: %s", os::strerror(errno)); + if (PrintMiscellaneous && Verbose) { + warning("could not truncate shared memory file: %s\n", os::strerror(errno)); + } ::close(fd); return -1; } // set the file size RESTARTABLE(::ftruncate(fd, (off_t)size), result); if (result == OS_ERR) { - log_debug(perf)("could not set shared memory file size: %s", os::strerror(errno)); + if (PrintMiscellaneous && Verbose) { + warning("could not set shared memory file size: %s\n", os::strerror(errno)); + } ::close(fd); return -1; } @@ -1039,7 +1057,9 @@ static char* mmap_create_shared(size_t size) { assert(result != OS_ERR, "could not close file"); if (mapAddress == MAP_FAILED) { - log_debug(perf)("mmap failed - %s", os::strerror(errno)); + if (PrintMiscellaneous && Verbose) { + warning("mmap failed - %s\n", os::strerror(errno)); + } remove_file(filename); FREE_C_HEAP_ARRAY(char, filename); return nullptr; @@ -1115,7 +1135,9 @@ static size_t sharedmem_filesize(int fd, TRAPS) { RESTARTABLE(::fstat(fd, &statbuf), result); if (result == OS_ERR) { - log_debug(perf)("fstat failed: %s", os::strerror(errno)); + if (PrintMiscellaneous && Verbose) { + warning("fstat failed: %s\n", os::strerror(errno)); + } THROW_MSG_0(vmSymbols::java_io_IOException(), "Could not determine PerfMemory size"); } @@ -1190,7 +1212,9 @@ static void mmap_attach_shared(int vmid, char** addr, size_t* sizep, TRAPS) { assert(result != OS_ERR, "could not close file"); if (mapAddress == MAP_FAILED) { - log_debug(perf)("mmap failed: %s", os::strerror(errno)); + if (PrintMiscellaneous && Verbose) { + warning("mmap failed: %s\n", os::strerror(errno)); + } THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), "Could not map PerfMemory"); } @@ -1220,9 +1244,13 @@ void PerfMemory::create_memory_region(size_t size) { else { _start = create_shared_memory(size); if (_start == nullptr) { + // creation of the shared memory region failed, attempt // to create a contiguous, non-shared memory region instead. - log_debug(perf)("Reverting to non-shared PerfMemory region."); + // + if (PrintMiscellaneous && Verbose) { + warning("Reverting to non-shared PerfMemory region.\n"); + } FLAG_SET_ERGO(PerfDisableSharedMem, true); _start = create_standard_memory(size); } diff --git a/src/hotspot/os/posix/signals_posix.cpp b/src/hotspot/os/posix/signals_posix.cpp index 5833e324070b0..714eac12d2245 100644 --- a/src/hotspot/os/posix/signals_posix.cpp +++ b/src/hotspot/os/posix/signals_posix.cpp @@ -42,7 +42,6 @@ #include "signals_posix.hpp" #include "suspendResume_posix.hpp" #include "utilities/checkedCast.hpp" -#include "utilities/deferredStatic.hpp" #include "utilities/events.hpp" #include "utilities/ostream.hpp" #include "utilities/parseInteger.hpp" @@ -168,9 +167,9 @@ static get_signal_t get_signal_action = nullptr; // suspend/resume support #if defined(__APPLE__) -static DeferredStatic sr_semaphore; + static OSXSemaphore sr_semaphore; #else -static DeferredStatic sr_semaphore; + static PosixSemaphore sr_semaphore; #endif // Signal number used to suspend/resume a thread @@ -178,7 +177,7 @@ static DeferredStatic sr_semaphore; int PosixSignals::SR_signum = SIGUSR2; // sun.misc.Signal support -static DeferredStatic sig_semaphore; +static Semaphore* sig_semaphore = nullptr; // a counter for each possible signal value static volatile jint pending_signals[NSIG+1] = { 0 }; @@ -352,16 +351,17 @@ static void jdk_misc_signal_init() { ::memset((void*)pending_signals, 0, sizeof(pending_signals)); // Initialize signal semaphore - int sem_count = 0; - sig_semaphore.initialize(sem_count); + sig_semaphore = new Semaphore(); } void os::signal_notify(int sig) { - // Signal thread is not created with ReduceSignalUsage and jdk_misc_signal_init - // initialization isn't called. - if (!ReduceSignalUsage) { + if (sig_semaphore != nullptr) { AtomicAccess::inc(&pending_signals[sig]); sig_semaphore->signal(); + } else { + // Signal thread is not created with ReduceSignalUsage and jdk_misc_signal_init + // initialization isn't called. + assert(ReduceSignalUsage, "signal semaphore should be created"); } } @@ -1696,7 +1696,7 @@ static void SR_handler(int sig, siginfo_t* siginfo, void* context) { pthread_sigmask(SIG_BLOCK, nullptr, &suspend_set); sigdelset(&suspend_set, PosixSignals::SR_signum); - sr_semaphore->signal(); + sr_semaphore.signal(); // wait here until we are resumed while (1) { @@ -1705,7 +1705,7 @@ static void SR_handler(int sig, siginfo_t* siginfo, void* context) { SuspendResume::State result = osthread->sr.running(); if (result == SuspendResume::SR_RUNNING) { // double check AIX doesn't need this! - sr_semaphore->signal(); + sr_semaphore.signal(); break; } else if (result != SuspendResume::SR_SUSPENDED) { ShouldNotReachHere(); @@ -1731,9 +1731,6 @@ static void SR_handler(int sig, siginfo_t* siginfo, void* context) { } static int SR_initialize() { - int sem_count = 0; - sr_semaphore.initialize(sem_count); - struct sigaction act; char *s; // Get signal number to use for suspend/resume @@ -1781,7 +1778,7 @@ static int sr_notify(OSThread* osthread) { // but this seems the normal response to library errors bool PosixSignals::do_suspend(OSThread* osthread) { assert(osthread->sr.is_running(), "thread should be running"); - assert(!sr_semaphore->trywait(), "semaphore has invalid state"); + assert(!sr_semaphore.trywait(), "semaphore has invalid state"); // mark as suspended and send signal if (osthread->sr.request_suspend() != SuspendResume::SR_SUSPEND_REQUEST) { @@ -1796,7 +1793,7 @@ bool PosixSignals::do_suspend(OSThread* osthread) { // managed to send the signal and switch to SUSPEND_REQUEST, now wait for SUSPENDED while (true) { - if (sr_semaphore->timedwait(2)) { + if (sr_semaphore.timedwait(2)) { break; } else { // timeout @@ -1805,7 +1802,7 @@ bool PosixSignals::do_suspend(OSThread* osthread) { return false; } else if (cancelled == SuspendResume::SR_SUSPENDED) { // make sure that we consume the signal on the semaphore as well - sr_semaphore->wait(); + sr_semaphore.wait(); break; } else { ShouldNotReachHere(); @@ -1820,7 +1817,7 @@ bool PosixSignals::do_suspend(OSThread* osthread) { void PosixSignals::do_resume(OSThread* osthread) { assert(osthread->sr.is_suspended(), "thread should be suspended"); - assert(!sr_semaphore->trywait(), "invalid semaphore state"); + assert(!sr_semaphore.trywait(), "invalid semaphore state"); if (osthread->sr.request_wakeup() != SuspendResume::SR_WAKEUP_REQUEST) { // failed to switch to WAKEUP_REQUEST @@ -1830,7 +1827,7 @@ void PosixSignals::do_resume(OSThread* osthread) { while (true) { if (sr_notify(osthread) == 0) { - if (sr_semaphore->timedwait(2)) { + if (sr_semaphore.timedwait(2)) { if (osthread->sr.is_running()) { return; } diff --git a/src/hotspot/os/windows/gc/z/zNUMA_windows.cpp b/src/hotspot/os/windows/gc/z/zNUMA_windows.cpp index e2bd68035844c..dc7521dde563f 100644 --- a/src/hotspot/os/windows/gc/z/zNUMA_windows.cpp +++ b/src/hotspot/os/windows/gc/z/zNUMA_windows.cpp @@ -46,7 +46,3 @@ uint32_t ZNUMA::memory_id(uintptr_t addr) { // NUMA support not enabled, assume everything belongs to node zero return 0; } - -int ZNUMA::numa_id_to_node(uint32_t numa_id) { - ShouldNotCallThis(); -} diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 7934c9d6ffbd4..ba05d390c9fe1 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -6259,106 +6259,3 @@ const void* os::get_saved_assert_context(const void** sigInfo) { *sigInfo = nullptr; return nullptr; } - -/* - * Windows/x64 does not use stack frames the way expected by Java: - * [1] in most cases, there is no frame pointer. All locals are addressed via RSP - * [2] in rare cases, when alloca() is used, a frame pointer is used, but this may - * not be RBP. - * See http://msdn.microsoft.com/en-us/library/ew5tede7.aspx - * - * So it's not possible to print the native stack using the - * while (...) {... fr = os::get_sender_for_C_frame(&fr); } - * loop in vmError.cpp. We need to roll our own loop. - * This approach works for Windows AArch64 as well. - */ -bool os::win32::platform_print_native_stack(outputStream* st, const void* context, - char* buf, int buf_size, address& lastpc) -{ - CONTEXT ctx; - if (context != nullptr) { - memcpy(&ctx, context, sizeof(ctx)); - } else { - RtlCaptureContext(&ctx); - } - - st->print_cr("Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)"); - - DWORD machine_type; - STACKFRAME stk; - memset(&stk, 0, sizeof(stk)); - stk.AddrStack.Mode = AddrModeFlat; - stk.AddrFrame.Mode = AddrModeFlat; - stk.AddrPC.Mode = AddrModeFlat; - -#if defined(_M_AMD64) - stk.AddrStack.Offset = ctx.Rsp; - stk.AddrFrame.Offset = ctx.Rbp; - stk.AddrPC.Offset = ctx.Rip; - machine_type = IMAGE_FILE_MACHINE_AMD64; -#elif defined(_M_ARM64) - stk.AddrStack.Offset = ctx.Sp; - stk.AddrFrame.Offset = ctx.Fp; - stk.AddrPC.Offset = ctx.Pc; - machine_type = IMAGE_FILE_MACHINE_ARM64; -#else - #error unknown architecture -#endif - - // Ensure we consider dynamically loaded DLLs - SymbolEngine::refreshModuleList(); - - int count = 0; - address lastpc_internal = 0; - while (count++ < StackPrintLimit) { - intptr_t* sp = (intptr_t*)stk.AddrStack.Offset; - intptr_t* fp = (intptr_t*)stk.AddrFrame.Offset; // NOT necessarily the same as ctx.Rbp! - address pc = (address)stk.AddrPC.Offset; - - if (pc != nullptr) { - if (count == 2 && lastpc_internal == pc) { - // Skip it -- StackWalk64() may return the same PC - // (but different SP) on the first try. - } else { - // Don't try to create a frame(sp, fp, pc) -- on WinX64, stk.AddrFrame - // may not contain what Java expects, and may cause the frame() constructor - // to crash. Let's just print out the symbolic address. - frame::print_C_frame(st, buf, buf_size, pc); - // print source file and line, if available - char buf[128]; - int line_no; - if (SymbolEngine::get_source_info(pc, buf, sizeof(buf), &line_no)) { - st->print(" (%s:%d)", buf, line_no); - } else { - st->print(" (no source info available)"); - } - st->cr(); - } - lastpc_internal = pc; - } - - PVOID p = WindowsDbgHelp::symFunctionTableAccess64(GetCurrentProcess(), stk.AddrPC.Offset); - if (p == nullptr) { - // StackWalk64() can't handle this PC. Calling StackWalk64 again may cause crash. - lastpc = lastpc_internal; - break; - } - - BOOL result = WindowsDbgHelp::stackWalk64( - machine_type, // __in DWORD MachineType, - GetCurrentProcess(), // __in HANDLE hProcess, - GetCurrentThread(), // __in HANDLE hThread, - &stk, // __inout LP STACKFRAME64 StackFrame, - &ctx); // __inout PVOID ContextRecord, - - if (!result) { - break; - } - } - if (count > StackPrintLimit) { - st->print_cr("......"); - } - st->cr(); - - return true; -} diff --git a/src/hotspot/os/windows/perfMemory_windows.cpp b/src/hotspot/os/windows/perfMemory_windows.cpp index f54a2b52ccadf..a9b2eebb7be0c 100644 --- a/src/hotspot/os/windows/perfMemory_windows.cpp +++ b/src/hotspot/os/windows/perfMemory_windows.cpp @@ -24,7 +24,6 @@ #include "classfile/vmSymbols.hpp" #include "logging/log.hpp" -#include "logging/logStream.hpp" #include "memory/allocation.inline.hpp" #include "memory/resourceArea.hpp" #include "nmt/memTracker.hpp" @@ -42,7 +41,11 @@ #include #include #include -#include + +typedef BOOL (WINAPI *SetSecurityDescriptorControlFnPtr)( + IN PSECURITY_DESCRIPTOR pSecurityDescriptor, + IN SECURITY_DESCRIPTOR_CONTROL ControlBitsOfInterest, + IN SECURITY_DESCRIPTOR_CONTROL ControlBitsToSet); // Standard Memory Implementation Details @@ -59,7 +62,9 @@ static char* create_standard_memory(size_t size) { // commit memory if (!os::commit_memory(mapAddress, size, !ExecMem)) { - log_debug(perf)("could not commit PerfData memory"); + if (PrintMiscellaneous && Verbose) { + warning("Could not commit PerfData memory\n"); + } os::release_memory(mapAddress, size); return nullptr; } @@ -85,21 +90,25 @@ static void delete_standard_memory(char* addr, size_t size) { static void save_memory_to_file(char* addr, size_t size) { const char* destfile = PerfMemory::get_perfdata_file_path(); - assert(destfile[0] != '\0', "invalid PerfData file path"); + assert(destfile[0] != '\0', "invalid Perfdata file path"); int fd = ::_open(destfile, _O_BINARY|_O_CREAT|_O_WRONLY|_O_TRUNC, _S_IREAD|_S_IWRITE); if (fd == OS_ERR) { - log_debug(perf)("could not create PerfData save file: %s: %s", - destfile, os::strerror(errno)); + if (PrintMiscellaneous && Verbose) { + warning("Could not create Perfdata save file: %s: %s\n", + destfile, os::strerror(errno)); + } } else { for (size_t remaining = size; remaining > 0;) { int nbytes = ::_write(fd, addr, (unsigned int)remaining); if (nbytes == OS_ERR) { - log_debug(perf)("could not write PerfData save file: %s: %s", - destfile, os::strerror(errno)); + if (PrintMiscellaneous && Verbose) { + warning("Could not write Perfdata save file: %s: %s\n", + destfile, os::strerror(errno)); + } break; } @@ -108,8 +117,10 @@ static void save_memory_to_file(char* addr, size_t size) { } int result = ::_close(fd); - if (result == OS_ERR) { - log_debug(perf)("could not close %s: %s", destfile, os::strerror(errno)); + if (PrintMiscellaneous && Verbose) { + if (result == OS_ERR) { + warning("Could not close %s: %s\n", destfile, os::strerror(errno)); + } } } @@ -209,8 +220,10 @@ static bool is_directory_secure(const char* path) { } else { // unexpected error, declare the path insecure - log_debug(perf)("could not get attributes for file %s: lasterror = %d", - path, lasterror); + if (PrintMiscellaneous && Verbose) { + warning("could not get attributes for file %s: " + " lasterror = %d\n", path, lasterror); + } return false; } } @@ -221,7 +234,9 @@ static bool is_directory_secure(const char* path) { // as some types of reparse points might be acceptable, but it // is probably more secure to avoid these conditions. // - log_debug(perf)("%s is a reparse point", path); + if (PrintMiscellaneous && Verbose) { + warning("%s is a reparse point\n", path); + } return false; } @@ -238,8 +253,10 @@ static bool is_directory_secure(const char* path) { // this is either a regular file or some other type of file, // any of which are unexpected and therefore insecure. // - log_debug(perf)("%s is not a directory, file attributes : " - INTPTR_FORMAT, path, fa); + if (PrintMiscellaneous && Verbose) { + warning("%s is not a directory, file attributes = " + INTPTR_FORMAT "\n", path, fa); + } return false; } } @@ -475,9 +492,11 @@ static void remove_file(const char* dirname, const char* filename) { strcat(path, filename); if (::unlink(path) == OS_ERR) { - if (errno != ENOENT) { - log_debug(perf)("could not unlink shared memory backing store file %s : %s", - path, os::strerror(errno)); + if (PrintMiscellaneous && Verbose) { + if (errno != ENOENT) { + warning("Could not unlink shared memory backing" + " store file %s : %s\n", path, os::strerror(errno)); + } } } @@ -496,16 +515,20 @@ static bool is_alive(int pid) { HANDLE ph = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); if (ph == nullptr) { // the process does not exist. - DWORD lastError = GetLastError(); - if (lastError != ERROR_INVALID_PARAMETER) { - log_debug(perf)("OpenProcess failed: %d", lastError); + if (PrintMiscellaneous && Verbose) { + DWORD lastError = GetLastError(); + if (lastError != ERROR_INVALID_PARAMETER) { + warning("OpenProcess failed: %d\n", GetLastError()); + } } return false; } DWORD exit_status; if (!GetExitCodeProcess(ph, &exit_status)) { - log_debug(perf)("GetExitCodeProcess failed: %d", GetLastError()); + if (PrintMiscellaneous && Verbose) { + warning("GetExitCodeProcess failed: %d\n", GetLastError()); + } CloseHandle(ph); return false; } @@ -522,13 +545,17 @@ static bool is_filesystem_secure(const char* path) { char fs_type[MAX_PATH]; if (PerfBypassFileSystemCheck) { - log_debug(perf)("bypassing file system criteria checks for %s", path); + if (PrintMiscellaneous && Verbose) { + warning("bypassing file system criteria checks for %s\n", path); + } return true; } char* first_colon = strchr((char *)path, ':'); if (first_colon == nullptr) { - log_debug(perf)("expected device specifier in path: %s", path); + if (PrintMiscellaneous && Verbose) { + warning("expected device specifier in path: %s\n", path); + } return false; } @@ -549,22 +576,29 @@ static bool is_filesystem_secure(const char* path) { if (!GetVolumeInformation(root_path, nullptr, 0, nullptr, &maxpath, &flags, fs_type, MAX_PATH)) { // we can't get information about the volume, so assume unsafe. - log_debug(perf)("could not get device information for %s: path = %s: lasterror = %d", - root_path, path, GetLastError()); + if (PrintMiscellaneous && Verbose) { + warning("could not get device information for %s: " + " path = %s: lasterror = %d\n", + root_path, path, GetLastError()); + } return false; } if ((flags & FS_PERSISTENT_ACLS) == 0) { // file system doesn't support ACLs, declare file system unsafe - log_debug(perf)("file system type %s on device %s does not support ACLs", - fs_type, root_path); + if (PrintMiscellaneous && Verbose) { + warning("file system type %s on device %s does not support" + " ACLs\n", fs_type, root_path); + } return false; } if ((flags & FS_VOL_IS_COMPRESSED) != 0) { // file system is compressed, declare file system unsafe - log_debug(perf)("file system type %s on device %s is compressed", - fs_type, root_path); + if (PrintMiscellaneous && Verbose) { + warning("file system type %s on device %s is compressed\n", + fs_type, root_path); + } return false; } @@ -670,7 +704,9 @@ static HANDLE create_file_mapping(const char* name, HANDLE fh, LPSECURITY_ATTRIB name); /* LPCTSTR name for object */ if (fmh == nullptr) { - log_debug(perf)("CreateFileMapping failed, lasterror = %d", GetLastError()); + if (PrintMiscellaneous && Verbose) { + warning("CreateFileMapping failed, lasterror = %d\n", GetLastError()); + } return nullptr; } @@ -681,7 +717,9 @@ static HANDLE create_file_mapping(const char* name, HANDLE fh, LPSECURITY_ATTRIB // the other processes either exit or close their mapping objects // and/or mapped views of this mapping object. // - log_debug(perf)("file mapping already exists, lasterror = %d", GetLastError()); + if (PrintMiscellaneous && Verbose) { + warning("file mapping already exists, lasterror = %d\n", GetLastError()); + } CloseHandle(fmh); return nullptr; @@ -745,7 +783,9 @@ static PSID get_user_sid(HANDLE hProcess) { // get the process token if (!OpenProcessToken(hProcess, TOKEN_READ, &hAccessToken)) { - log_debug(perf)("OpenProcessToken failure: lasterror = %d", GetLastError()); + if (PrintMiscellaneous && Verbose) { + warning("OpenProcessToken failure: lasterror = %d \n", GetLastError()); + } return nullptr; } @@ -755,8 +795,10 @@ static PSID get_user_sid(HANDLE hProcess) { if (!GetTokenInformation(hAccessToken, TokenUser, nullptr, rsize, &rsize)) { DWORD lasterror = GetLastError(); if (lasterror != ERROR_INSUFFICIENT_BUFFER) { - log_debug(perf)("GetTokenInformation failure: lasterror = %d, rsize = %d", - lasterror, rsize); + if (PrintMiscellaneous && Verbose) { + warning("GetTokenInformation failure: lasterror = %d," + " rsize = %d\n", lasterror, rsize); + } CloseHandle(hAccessToken); return nullptr; } @@ -766,8 +808,10 @@ static PSID get_user_sid(HANDLE hProcess) { // get the user token information if (!GetTokenInformation(hAccessToken, TokenUser, token_buf, rsize, &rsize)) { - log_debug(perf)("GetTokenInformation failure: lasterror = %d, rsize = %d", - GetLastError(), rsize); + if (PrintMiscellaneous && Verbose) { + warning("GetTokenInformation failure: lasterror = %d," + " rsize = %d\n", GetLastError(), rsize); + } FREE_C_HEAP_ARRAY(char, token_buf); CloseHandle(hAccessToken); return nullptr; @@ -777,8 +821,10 @@ static PSID get_user_sid(HANDLE hProcess) { PSID pSID = NEW_C_HEAP_ARRAY(char, nbytes, mtInternal); if (!CopySid(nbytes, pSID, token_buf->User.Sid)) { - log_debug(perf)("GetTokenInformation failure: lasterror = %d, rsize = %d", - GetLastError(), rsize); + if (PrintMiscellaneous && Verbose) { + warning("GetTokenInformation failure: lasterror = %d," + " rsize = %d\n", GetLastError(), rsize); + } FREE_C_HEAP_ARRAY(char, token_buf); FREE_C_HEAP_ARRAY(char, pSID); CloseHandle(hAccessToken); @@ -820,8 +866,10 @@ static bool add_allow_aces(PSECURITY_DESCRIPTOR pSD, // retrieve any existing access control list. if (!GetSecurityDescriptorDacl(pSD, &exists, &oldACL, &isdefault)) { - log_debug(perf)("GetSecurityDescriptor failure: lasterror = %d", - GetLastError()); + if (PrintMiscellaneous && Verbose) { + warning("GetSecurityDescriptor failure: lasterror = %d \n", + GetLastError()); + } return false; } @@ -838,8 +886,10 @@ static bool add_allow_aces(PSECURITY_DESCRIPTOR pSD, if (!GetAclInformation(oldACL, &aclinfo, sizeof(ACL_SIZE_INFORMATION), AclSizeInformation)) { - log_debug(perf)("GetAclInformation failure: lasterror = %d", GetLastError()); - return false; + if (PrintMiscellaneous && Verbose) { + warning("GetAclInformation failure: lasterror = %d \n", GetLastError()); + return false; + } } } else { aclinfo.AceCount = 0; // assume null DACL @@ -864,7 +914,9 @@ static bool add_allow_aces(PSECURITY_DESCRIPTOR pSD, newACL = (PACL) NEW_C_HEAP_ARRAY(char, newACLsize, mtInternal); if (!InitializeAcl(newACL, newACLsize, ACL_REVISION)) { - log_debug(perf)("InitializeAcl failure: lasterror = %d", GetLastError()); + if (PrintMiscellaneous && Verbose) { + warning("InitializeAcl failure: lasterror = %d \n", GetLastError()); + } FREE_C_HEAP_ARRAY(char, newACL); return false; } @@ -875,7 +927,9 @@ static bool add_allow_aces(PSECURITY_DESCRIPTOR pSD, while (ace_index < aclinfo.AceCount) { LPVOID ace; if (!GetAce(oldACL, ace_index, &ace)) { - log_debug(perf)("InitializeAcl failure: lasterror = %d", GetLastError()); + if (PrintMiscellaneous && Verbose) { + warning("InitializeAcl failure: lasterror = %d \n", GetLastError()); + } FREE_C_HEAP_ARRAY(char, newACL); return false; } @@ -900,7 +954,9 @@ static bool add_allow_aces(PSECURITY_DESCRIPTOR pSD, if (matches == 0) { if (!AddAce(newACL, ACL_REVISION, MAXDWORD, ace, ((PACE_HEADER)ace)->AceSize)) { - log_debug(perf)("AddAce failure: lasterror = %d", GetLastError()); + if (PrintMiscellaneous && Verbose) { + warning("AddAce failure: lasterror = %d \n", GetLastError()); + } FREE_C_HEAP_ARRAY(char, newACL); return false; } @@ -913,8 +969,10 @@ static bool add_allow_aces(PSECURITY_DESCRIPTOR pSD, for (int i = 0; i < ace_count; i++) { if (!AddAccessAllowedAce(newACL, ACL_REVISION, aces[i].mask, aces[i].pSid)) { - log_debug(perf)("AddAccessAllowedAce failure: lasterror = %d", - GetLastError()); + if (PrintMiscellaneous && Verbose) { + warning("AddAccessAllowedAce failure: lasterror = %d \n", + GetLastError()); + } FREE_C_HEAP_ARRAY(char, newACL); return false; } @@ -927,13 +985,17 @@ static bool add_allow_aces(PSECURITY_DESCRIPTOR pSD, while (ace_index < aclinfo.AceCount) { LPVOID ace; if (!GetAce(oldACL, ace_index, &ace)) { - log_debug(perf)("InitializeAcl failure: lasterror = %d", GetLastError()); + if (PrintMiscellaneous && Verbose) { + warning("InitializeAcl failure: lasterror = %d \n", GetLastError()); + } FREE_C_HEAP_ARRAY(char, newACL); return false; } if (!AddAce(newACL, ACL_REVISION, MAXDWORD, ace, ((PACE_HEADER)ace)->AceSize)) { - log_debug(perf)("AddAce failure: lasterror = %d", GetLastError()); + if (PrintMiscellaneous && Verbose) { + warning("AddAce failure: lasterror = %d \n", GetLastError()); + } FREE_C_HEAP_ARRAY(char, newACL); return false; } @@ -943,23 +1005,39 @@ static bool add_allow_aces(PSECURITY_DESCRIPTOR pSD, // add the new ACL to the security descriptor. if (!SetSecurityDescriptorDacl(pSD, TRUE, newACL, FALSE)) { - log_debug(perf)("SetSecurityDescriptorDacl failure: lasterror = %d", GetLastError()); + if (PrintMiscellaneous && Verbose) { + warning("SetSecurityDescriptorDacl failure:" + " lasterror = %d \n", GetLastError()); + } FREE_C_HEAP_ARRAY(char, newACL); return false; } - // We do not want to further propagate inherited DACLs, so making them - // protected prevents that. - if (!SetSecurityDescriptorControl(pSD, SE_DACL_PROTECTED, SE_DACL_PROTECTED)) { - log_debug(perf)("SetSecurityDescriptorControl failure: lasterror = %d", GetLastError()); - FREE_C_HEAP_ARRAY(char, newACL); - return false; + // if running on windows 2000 or later, set the automatic inheritance + // control flags. + SetSecurityDescriptorControlFnPtr _SetSecurityDescriptorControl; + _SetSecurityDescriptorControl = (SetSecurityDescriptorControlFnPtr) + GetProcAddress(GetModuleHandle(TEXT("advapi32.dll")), + "SetSecurityDescriptorControl"); + + if (_SetSecurityDescriptorControl != nullptr) { + // We do not want to further propagate inherited DACLs, so making them + // protected prevents that. + if (!_SetSecurityDescriptorControl(pSD, SE_DACL_PROTECTED, + SE_DACL_PROTECTED)) { + if (PrintMiscellaneous && Verbose) { + warning("SetSecurityDescriptorControl failure:" + " lasterror = %d \n", GetLastError()); + } + FREE_C_HEAP_ARRAY(char, newACL); + return false; + } } - - // Note, the security descriptor maintains a reference to the newACL, not - // a copy of it. Therefore, the newACL is not freed here. It is freed when - // the security descriptor containing its reference is freed. - return true; + // Note, the security descriptor maintains a reference to the newACL, not + // a copy of it. Therefore, the newACL is not freed here. It is freed when + // the security descriptor containing its reference is freed. + // + return true; } // method to create a security attributes structure, which contains a @@ -979,7 +1057,10 @@ static LPSECURITY_ATTRIBUTES make_security_attr(ace_data_t aces[], int count) { // initialize the security descriptor if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) { - log_debug(perf)("InitializeSecurityDescriptor failure: lasterror = %d", GetLastError()); + if (PrintMiscellaneous && Verbose) { + warning("InitializeSecurityDescriptor failure: " + "lasterror = %d \n", GetLastError()); + } free_security_desc(pSD); return nullptr; } @@ -1032,7 +1113,11 @@ static LPSECURITY_ATTRIBUTES make_user_everybody_admin_security_attr( SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &administratorsSid)) { - log_debug(perf)("AllocateAndInitializeSid failure: lasterror = %d", GetLastError()); + + if (PrintMiscellaneous && Verbose) { + warning("AllocateAndInitializeSid failure: " + "lasterror = %d \n", GetLastError()); + } return nullptr; } @@ -1046,7 +1131,11 @@ static LPSECURITY_ATTRIBUTES make_user_everybody_admin_security_attr( if (!AllocateAndInitializeSid( &SIDAuthEverybody, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &everybodySid)) { - log_debug(perf)("AllocateAndInitializeSid failure: lasterror = %d", GetLastError()); + + if (PrintMiscellaneous && Verbose) { + warning("AllocateAndInitializeSid failure: " + "lasterror = %d \n", GetLastError()); + } return nullptr; } @@ -1147,7 +1236,9 @@ static bool make_user_tmp_dir(const char* dirname) { // if (!is_directory_secure(dirname)) { // directory is not secure - log_debug(perf)("%s directory is insecure", dirname); + if (PrintMiscellaneous && Verbose) { + warning("%s directory is insecure\n", dirname); + } free_security_attr(pDirSA); return false; } @@ -1158,11 +1249,16 @@ static bool make_user_tmp_dir(const char* dirname) { // DACLs might fix the corrupted the DACLs. SECURITY_INFORMATION secInfo = DACL_SECURITY_INFORMATION; if (!SetFileSecurity(dirname, secInfo, pDirSA->lpSecurityDescriptor)) { - lasterror = GetLastError(); - log_debug(perf)("SetFileSecurity failed for %s directory. lasterror = %d", dirname, lasterror); + if (PrintMiscellaneous && Verbose) { + lasterror = GetLastError(); + warning("SetFileSecurity failed for %s directory. lasterror %d \n", + dirname, lasterror); + } } } else { - log_debug(perf)("CreateDirectory failed: %d", GetLastError()); + if (PrintMiscellaneous && Verbose) { + warning("CreateDirectory failed: %d\n", GetLastError()); + } free_security_attr(pDirSA); return false; } @@ -1229,7 +1325,9 @@ static HANDLE create_sharedmem_resources(const char* dirname, const char* filena if (fh == INVALID_HANDLE_VALUE) { DWORD lasterror = GetLastError(); - log_debug(perf)("could not create file %s: %d", filename, lasterror); + if (PrintMiscellaneous && Verbose) { + warning("could not create file %s: %d\n", filename, lasterror); + } free_security_attr(lpSmoSA); return nullptr; } @@ -1255,8 +1353,10 @@ static HANDLE create_sharedmem_resources(const char* dirname, const char* filena struct stat statbuf; int ret_code = ::stat(filename, &statbuf); if (ret_code == OS_ERR) { - log_debug(perf)("could not get status information from file %s: %s", - filename, os::strerror(errno)); + if (PrintMiscellaneous && Verbose) { + warning("Could not get status information from file %s: %s\n", + filename, os::strerror(errno)); + } CloseHandle(fmh); CloseHandle(fh); fh = nullptr; @@ -1269,7 +1369,9 @@ static HANDLE create_sharedmem_resources(const char* dirname, const char* filena // call it when we observe the size as zero (0). if (statbuf.st_size == 0 && FlushFileBuffers(fh) != TRUE) { DWORD lasterror = GetLastError(); - log_debug(perf)("could not flush file %s: %d", filename, lasterror); + if (PrintMiscellaneous && Verbose) { + warning("could not flush file %s: %d\n", filename, lasterror); + } CloseHandle(fmh); CloseHandle(fh); fh = nullptr; @@ -1300,8 +1402,10 @@ static HANDLE open_sharedmem_object(const char* objectname, DWORD ofm_access, TR if (fmh == nullptr) { DWORD lasterror = GetLastError(); - log_debug(perf)("OpenFileMapping failed for shared memory object %s:" - " lasterror = %d", objectname, lasterror); + if (PrintMiscellaneous && Verbose) { + warning("OpenFileMapping failed for shared memory object %s:" + " lasterror = %d\n", objectname, lasterror); + } THROW_MSG_(vmSymbols::java_lang_IllegalArgumentException(), err_msg("Could not open PerfMemory, error %d", lasterror), INVALID_HANDLE_VALUE); @@ -1381,7 +1485,9 @@ static char* mapping_create_shared(size_t size) { (DWORD)size); /* DWORD Number of bytes to map */ if (mapAddress == nullptr) { - log_debug(perf)("MapViewOfFile failed, lasterror = %d", GetLastError()); + if (PrintMiscellaneous && Verbose) { + warning("MapViewOfFile failed, lasterror = %d\n", GetLastError()); + } CloseHandle(sharedmem_fileMapHandle); sharedmem_fileMapHandle = nullptr; return nullptr; @@ -1445,14 +1551,20 @@ static size_t sharedmem_filesize(const char* filename, TRAPS) { // inconsistencies // if (::stat(filename, &statbuf) == OS_ERR) { - log_debug(perf)("stat %s failed: %s", filename, os::strerror(errno)); + if (PrintMiscellaneous && Verbose) { + warning("stat %s failed: %s\n", filename, os::strerror(errno)); + } THROW_MSG_0(vmSymbols::java_io_IOException(), "Could not determine PerfMemory size"); } if ((statbuf.st_size == 0) || (statbuf.st_size % os::vm_page_size() != 0)) { - log_debug(perf)("unexpected file size: size = %zu", statbuf.st_size); - THROW_MSG_0(vmSymbols::java_io_IOException(), "Invalid PerfMemory size"); + if (PrintMiscellaneous && Verbose) { + warning("unexpected file size: size = %zu\n", + statbuf.st_size); + } + THROW_MSG_0(vmSymbols::java_io_IOException(), + "Invalid PerfMemory size"); } return statbuf.st_size; @@ -1525,7 +1637,9 @@ static void open_file_mapping(int vmid, char** addrp, size_t* sizep, TRAPS) { size); /* DWORD Number of bytes to map */ if (mapAddress == nullptr) { - log_debug(perf)("MapViewOfFile failed, lasterror = %d", GetLastError()); + if (PrintMiscellaneous && Verbose) { + warning("MapViewOfFile failed, lasterror = %d\n", GetLastError()); + } CloseHandle(fmh); THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), "Could not map PerfMemory"); @@ -1594,7 +1708,9 @@ void PerfMemory::create_memory_region(size_t size) { // creation of the shared memory region failed, attempt // to create a contiguous, non-shared memory region instead. // - log_debug(perf)("Reverting to non-shared PerfMemory region."); + if (PrintMiscellaneous && Verbose) { + warning("Reverting to non-shared PerfMemory region.\n"); + } FLAG_SET_ERGO(PerfDisableSharedMem, true); _start = create_standard_memory(size); } diff --git a/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp b/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp index ec756c44fe6f4..017d8a43666ab 100644 --- a/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp +++ b/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp @@ -167,19 +167,26 @@ static bool is_set(int64_t key, uint64_t value_mask) { void RiscvHwprobe::add_features_from_query_result() { assert(rw_hwprobe_completed, "hwprobe not init yet."); - // ====== extensions ====== - // + if (is_valid(RISCV_HWPROBE_KEY_MVENDORID)) { + VM_Version::mvendorid.enable_feature(query[RISCV_HWPROBE_KEY_MVENDORID].value); + } + if (is_valid(RISCV_HWPROBE_KEY_MARCHID)) { + VM_Version::marchid.enable_feature(query[RISCV_HWPROBE_KEY_MARCHID].value); + } + if (is_valid(RISCV_HWPROBE_KEY_MIMPID)) { + VM_Version::mimpid.enable_feature(query[RISCV_HWPROBE_KEY_MIMPID].value); + } if (is_set(RISCV_HWPROBE_KEY_BASE_BEHAVIOR, RISCV_HWPROBE_BASE_BEHAVIOR_IMA)) { - VM_Version::ext_a.enable_feature(); VM_Version::ext_i.enable_feature(); VM_Version::ext_m.enable_feature(); - } - if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_IMA_C)) { - VM_Version::ext_c.enable_feature(); + VM_Version::ext_a.enable_feature(); } if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_IMA_FD)) { - VM_Version::ext_d.enable_feature(); VM_Version::ext_f.enable_feature(); + VM_Version::ext_d.enable_feature(); + } + if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_IMA_C)) { + VM_Version::ext_c.enable_feature(); } if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_IMA_V)) { // Linux signal return bug when using vector with vlen > 128b in pre 6.8.5. @@ -195,29 +202,21 @@ void RiscvHwprobe::add_features_from_query_result() { VM_Version::ext_v.enable_feature(); } } - -#ifndef PRODUCT - if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZACAS)) { - VM_Version::ext_Zacas.enable_feature(); - } -#endif if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZBA)) { VM_Version::ext_Zba.enable_feature(); } if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZBB)) { VM_Version::ext_Zbb.enable_feature(); } -#ifndef PRODUCT - if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZBKB)) { - VM_Version::ext_Zbkb.enable_feature(); - } -#endif if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZBS)) { VM_Version::ext_Zbs.enable_feature(); } #ifndef PRODUCT - if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZFA)) { - VM_Version::ext_Zfa.enable_feature(); + 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(); } #endif if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZFH)) { @@ -227,28 +226,15 @@ void RiscvHwprobe::add_features_from_query_result() { VM_Version::ext_Zfhmin.enable_feature(); } #ifndef PRODUCT - if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZICBOZ)) { - VM_Version::ext_Zicboz.enable_feature(); - } - // Currently tests shows that cmove using Zicond instructions will bring - // performance regression, but to get a test coverage all the time, will - // still prefer to enabling it in debug version. - if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZICOND)) { - VM_Version::ext_Zicond.enable_feature(); - } - if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZTSO)) { - VM_Version::ext_Ztso.enable_feature(); - } if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZVBB)) { VM_Version::ext_Zvbb.enable_feature(); } +#endif +#ifndef PRODUCT if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZVBC)) { VM_Version::ext_Zvbc.enable_feature(); } #endif - if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZVFH)) { - VM_Version::ext_Zvfh.enable_feature(); - } #ifndef PRODUCT if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZVKNED) && is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZVKNHB) && @@ -257,18 +243,30 @@ void RiscvHwprobe::add_features_from_query_result() { VM_Version::ext_Zvkn.enable_feature(); } #endif - - // ====== non-extensions ====== - // - if (is_valid(RISCV_HWPROBE_KEY_MARCHID)) { - VM_Version::marchid.enable_feature(query[RISCV_HWPROBE_KEY_MARCHID].value); + if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZVFH)) { + VM_Version::ext_Zvfh.enable_feature(); } - if (is_valid(RISCV_HWPROBE_KEY_MIMPID)) { - VM_Version::mimpid.enable_feature(query[RISCV_HWPROBE_KEY_MIMPID].value); +#ifndef PRODUCT + if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZFA)) { + VM_Version::ext_Zfa.enable_feature(); } - if (is_valid(RISCV_HWPROBE_KEY_MVENDORID)) { - VM_Version::mvendorid.enable_feature(query[RISCV_HWPROBE_KEY_MVENDORID].value); +#endif +#ifndef PRODUCT + if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZTSO)) { + VM_Version::ext_Ztso.enable_feature(); + } +#endif +#ifndef PRODUCT + if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZACAS)) { + VM_Version::ext_Zacas.enable_feature(); + } + // Currently tests shows that cmove using Zicond instructions will bring + // performance regression, but to get a test coverage all the time, will + // still prefer to enabling it in debug version. + if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZICOND)) { + VM_Version::ext_Zicond.enable_feature(); } +#endif // RISCV_HWPROBE_KEY_CPUPERF_0 is deprecated and returns similar values // to RISCV_HWPROBE_KEY_MISALIGNED_SCALAR_PERF. Keep it there for backward // compatibility with old kernels. @@ -279,6 +277,7 @@ void RiscvHwprobe::add_features_from_query_result() { VM_Version::unaligned_scalar.enable_feature( query[RISCV_HWPROBE_KEY_MISALIGNED_SCALAR_PERF].value); } + if (is_valid(RISCV_HWPROBE_KEY_MISALIGNED_VECTOR_PERF)) { VM_Version::unaligned_vector.enable_feature( query[RISCV_HWPROBE_KEY_MISALIGNED_VECTOR_PERF].value); diff --git a/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp b/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp index 0799de014a976..e414a3889c231 100644 --- a/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp +++ b/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp @@ -103,14 +103,6 @@ uint32_t VM_Version::cpu_vector_length() { return (uint32_t)read_csr(CSR_VLENB); } -void VM_Version::RVExtFeatureValue::log_enabled() { - log_debug(os, cpu)("Enabled RV64 feature \"%s\"", pretty()); -} - -void VM_Version::RVNonExtFeatureValue::log_enabled() { - log_debug(os, cpu)("Enabled RV64 feature \"%s\" (%ld)", pretty(), value()); -} - void VM_Version::setup_cpu_available_features() { assert(ext_i.feature_bit() == HWCAP_ISA_I, "Bit for I must follow Linux HWCAP"); @@ -152,8 +144,9 @@ void VM_Version::setup_cpu_available_features() { continue; } - _feature_list[i]->log_enabled(); - + log_debug(os, cpu)("Enabled RV64 feature \"%s\" (%ld)", + _feature_list[i]->pretty(), + _feature_list[i]->value()); // The feature string if (_feature_list[i]->feature_string()) { const char* tmp = _feature_list[i]->pretty(); diff --git a/src/hotspot/os_cpu/windows_aarch64/os_windows_aarch64.inline.hpp b/src/hotspot/os_cpu/windows_aarch64/os_windows_aarch64.inline.hpp index 568b6e3938ee7..794aa12155b17 100644 --- a/src/hotspot/os_cpu/windows_aarch64/os_windows_aarch64.inline.hpp +++ b/src/hotspot/os_cpu/windows_aarch64/os_windows_aarch64.inline.hpp @@ -26,17 +26,10 @@ #define OS_CPU_WINDOWS_AARCH64_OS_WINDOWS_AARCH64_INLINE_HPP #include "runtime/os.hpp" -#include "os_windows.hpp" inline bool os::register_code_area(char *low, char *high) { // Using Vectored Exception Handling return true; } -#define HAVE_PLATFORM_PRINT_NATIVE_STACK 1 -inline bool os::platform_print_native_stack(outputStream* st, const void* context, - char *buf, int buf_size, address& lastpc) { - return os::win32::platform_print_native_stack(st, context, buf, buf_size, lastpc); -} - #endif // OS_CPU_WINDOWS_AARCH64_OS_WINDOWS_AARCH64_INLINE_HPP diff --git a/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp b/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp index 53f9647983248..c188919595c9d 100644 --- a/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp +++ b/src/hotspot/os_cpu/windows_x86/os_windows_x86.cpp @@ -197,6 +197,98 @@ bool handle_FLT_exception(struct _EXCEPTION_POINTERS* exceptionInfo) { } #endif +#ifdef HAVE_PLATFORM_PRINT_NATIVE_STACK +/* + * Windows/x64 does not use stack frames the way expected by Java: + * [1] in most cases, there is no frame pointer. All locals are addressed via RSP + * [2] in rare cases, when alloca() is used, a frame pointer is used, but this may + * not be RBP. + * See http://msdn.microsoft.com/en-us/library/ew5tede7.aspx + * + * So it's not possible to print the native stack using the + * while (...) {... fr = os::get_sender_for_C_frame(&fr); } + * loop in vmError.cpp. We need to roll our own loop. + */ +bool os::win32::platform_print_native_stack(outputStream* st, const void* context, + char *buf, int buf_size, address& lastpc) +{ + CONTEXT ctx; + if (context != nullptr) { + memcpy(&ctx, context, sizeof(ctx)); + } else { + RtlCaptureContext(&ctx); + } + + st->print_cr("Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)"); + + STACKFRAME stk; + memset(&stk, 0, sizeof(stk)); + stk.AddrStack.Offset = ctx.Rsp; + stk.AddrStack.Mode = AddrModeFlat; + stk.AddrFrame.Offset = ctx.Rbp; + stk.AddrFrame.Mode = AddrModeFlat; + stk.AddrPC.Offset = ctx.Rip; + stk.AddrPC.Mode = AddrModeFlat; + + // Ensure we consider dynamically loaded dll's + SymbolEngine::refreshModuleList(); + + int count = 0; + address lastpc_internal = 0; + while (count++ < StackPrintLimit) { + intptr_t* sp = (intptr_t*)stk.AddrStack.Offset; + intptr_t* fp = (intptr_t*)stk.AddrFrame.Offset; // NOT necessarily the same as ctx.Rbp! + address pc = (address)stk.AddrPC.Offset; + + if (pc != nullptr) { + if (count == 2 && lastpc_internal == pc) { + // Skip it -- StackWalk64() may return the same PC + // (but different SP) on the first try. + } else { + // Don't try to create a frame(sp, fp, pc) -- on WinX64, stk.AddrFrame + // may not contain what Java expects, and may cause the frame() constructor + // to crash. Let's just print out the symbolic address. + frame::print_C_frame(st, buf, buf_size, pc); + // print source file and line, if available + char buf[128]; + int line_no; + if (SymbolEngine::get_source_info(pc, buf, sizeof(buf), &line_no)) { + st->print(" (%s:%d)", buf, line_no); + } else { + st->print(" (no source info available)"); + } + st->cr(); + } + lastpc_internal = pc; + } + + PVOID p = WindowsDbgHelp::symFunctionTableAccess64(GetCurrentProcess(), stk.AddrPC.Offset); + if (!p) { + // StackWalk64() can't handle this PC. Calling StackWalk64 again may cause crash. + lastpc = lastpc_internal; + break; + } + + BOOL result = WindowsDbgHelp::stackWalk64( + IMAGE_FILE_MACHINE_AMD64, // __in DWORD MachineType, + GetCurrentProcess(), // __in HANDLE hProcess, + GetCurrentThread(), // __in HANDLE hThread, + &stk, // __inout LP STACKFRAME64 StackFrame, + &ctx); // __inout PVOID ContextRecord, + + if (!result) { + break; + } + } + if (count > StackPrintLimit) { + st->print_cr("......"); + } + st->cr(); + + return true; +} +#endif // HAVE_PLATFORM_PRINT_NATIVE_STACK + address os::fetch_frame_from_context(const void* ucVoid, intptr_t** ret_sp, intptr_t** ret_fp) { diff --git a/src/hotspot/share/adlc/archDesc.cpp b/src/hotspot/share/adlc/archDesc.cpp index 2461903ea268f..263752c521d6f 100644 --- a/src/hotspot/share/adlc/archDesc.cpp +++ b/src/hotspot/share/adlc/archDesc.cpp @@ -899,12 +899,10 @@ int ArchDesc::emit_msg(int quiet, int flag, int line, const char *fmt, // Construct the name of the register mask. static const char *getRegMask(const char *reg_class_name) { - if (reg_class_name == nullptr) { - return "RegMask::EMPTY"; - } + if( reg_class_name == nullptr ) return "RegMask::Empty"; if (strcmp(reg_class_name,"Universe")==0) { - return "RegMask::EMPTY"; + return "RegMask::Empty"; } else if (strcmp(reg_class_name,"stack_slots")==0) { return "(Compile::current()->FIRST_STACK_mask())"; } else if (strcmp(reg_class_name, "dynamic")==0) { @@ -922,7 +920,7 @@ static const char *getRegMask(const char *reg_class_name) { // Convert a register class name to its register mask. const char *ArchDesc::reg_class_to_reg_mask(const char *rc_name) { - const char* reg_mask = "RegMask::EMPTY"; + const char *reg_mask = "RegMask::Empty"; if( _register ) { RegClass *reg_class = _register->getRegClass(rc_name); @@ -941,7 +939,7 @@ const char *ArchDesc::reg_class_to_reg_mask(const char *rc_name) { // Obtain the name of the RegMask for an OperandForm const char *ArchDesc::reg_mask(OperandForm &opForm) { - const char* regMask = "RegMask::EMPTY"; + const char *regMask = "RegMask::Empty"; // Check constraints on result's register class const char *result_class = opForm.constrained_reg_class(); @@ -970,9 +968,9 @@ const char *ArchDesc::reg_mask(InstructForm &inForm) { abort(); } - // Instructions producing 'Universe' use RegMask::EMPTY + // Instructions producing 'Universe' use RegMask::Empty if (strcmp(result,"Universe") == 0) { - return "RegMask::EMPTY"; + return "RegMask::Empty"; } // Lookup this result operand and get its register class diff --git a/src/hotspot/share/adlc/formssel.cpp b/src/hotspot/share/adlc/formssel.cpp index 182587d2f2fde..b938d5b75608d 100644 --- a/src/hotspot/share/adlc/formssel.cpp +++ b/src/hotspot/share/adlc/formssel.cpp @@ -2422,7 +2422,7 @@ const char *OperandForm::constrained_reg_class() const { // Return the register class associated with 'leaf'. const char *OperandForm::in_reg_class(uint leaf, FormDict &globals) { - const char* reg_class = nullptr; // "RegMask::EMPTY"; + const char *reg_class = nullptr; // "RegMask::Empty"; if((_matrule == nullptr) || (_matrule->is_chain_rule(globals))) { reg_class = constrained_reg_class(); diff --git a/src/hotspot/share/adlc/output_c.cpp b/src/hotspot/share/adlc/output_c.cpp index 110db7f0e9810..caf2c9952a681 100644 --- a/src/hotspot/share/adlc/output_c.cpp +++ b/src/hotspot/share/adlc/output_c.cpp @@ -2837,7 +2837,7 @@ static void defineIn_RegMask(FILE *fp, FormDict &globals, OperandForm &oper) { if (strcmp(first_reg_class, "stack_slots") == 0) { fprintf(fp," return &(Compile::current()->FIRST_STACK_mask());\n"); } else if (strcmp(first_reg_class, "dynamic") == 0) { - fprintf(fp, " return &RegMask::EMPTY;\n"); + fprintf(fp," return &RegMask::Empty;\n"); } else { const char* first_reg_class_to_upper = toUpper(first_reg_class); fprintf(fp," return &%s_mask();\n", first_reg_class_to_upper); diff --git a/src/hotspot/share/cds/aotConstantPoolResolver.cpp b/src/hotspot/share/cds/aotConstantPoolResolver.cpp index 8b4e60dece2d8..6cc3a81c2ae1a 100644 --- a/src/hotspot/share/cds/aotConstantPoolResolver.cpp +++ b/src/hotspot/share/cds/aotConstantPoolResolver.cpp @@ -225,38 +225,7 @@ void AOTConstantPoolResolver::preresolve_field_and_method_cp_entries(JavaThread* Bytecodes::Code raw_bc = bcs.raw_code(); switch (raw_bc) { case Bytecodes::_getfield: - // no-fast bytecode - case Bytecodes::_nofast_getfield: - // fast bytecodes - case Bytecodes::_fast_agetfield: - case Bytecodes::_fast_bgetfield: - case Bytecodes::_fast_cgetfield: - case Bytecodes::_fast_dgetfield: - case Bytecodes::_fast_fgetfield: - case Bytecodes::_fast_igetfield: - case Bytecodes::_fast_lgetfield: - case Bytecodes::_fast_sgetfield: - raw_bc = Bytecodes::_getfield; - maybe_resolve_fmi_ref(ik, m, raw_bc, bcs.get_index_u2(), preresolve_list, THREAD); - if (HAS_PENDING_EXCEPTION) { - CLEAR_PENDING_EXCEPTION; // just ignore - } - break; - case Bytecodes::_putfield: - // no-fast bytecode - case Bytecodes::_nofast_putfield: - // fast bytecodes - case Bytecodes::_fast_aputfield: - case Bytecodes::_fast_bputfield: - case Bytecodes::_fast_zputfield: - case Bytecodes::_fast_cputfield: - case Bytecodes::_fast_dputfield: - case Bytecodes::_fast_fputfield: - case Bytecodes::_fast_iputfield: - case Bytecodes::_fast_lputfield: - case Bytecodes::_fast_sputfield: - raw_bc = Bytecodes::_putfield; maybe_resolve_fmi_ref(ik, m, raw_bc, bcs.get_index_u2(), preresolve_list, THREAD); if (HAS_PENDING_EXCEPTION) { CLEAR_PENDING_EXCEPTION; // just ignore diff --git a/src/hotspot/share/cds/aotLinkedClassBulkLoader.cpp b/src/hotspot/share/cds/aotLinkedClassBulkLoader.cpp index 3653f9d518c3f..e7145b25457c0 100644 --- a/src/hotspot/share/cds/aotLinkedClassBulkLoader.cpp +++ b/src/hotspot/share/cds/aotLinkedClassBulkLoader.cpp @@ -42,8 +42,6 @@ #include "oops/trainingData.hpp" #include "runtime/handles.inline.hpp" #include "runtime/java.hpp" -#include "runtime/serviceThread.hpp" -#include "utilities/growableArray.hpp" void AOTLinkedClassBulkLoader::serialize(SerializeClosure* soc) { AOTLinkedClassTable::get()->serialize(soc); @@ -55,8 +53,6 @@ void AOTLinkedClassBulkLoader::serialize(SerializeClosure* soc) { // step in restoring the JVM's state from the snapshot recorded in the AOT cache: other AOT optimizations // such as AOT compiled methods can make direct references to the preloaded classes, knowing that // these classes are guaranteed to be in at least the "loaded" state. -// -// Note: we can't link the classes yet because SharedRuntime is not yet ready to generate adapters. void AOTLinkedClassBulkLoader::preload_classes(JavaThread* current) { preload_classes_impl(current); if (current->has_pending_exception()) { @@ -116,44 +112,6 @@ void AOTLinkedClassBulkLoader::preload_classes_in_table(Array* c } } -// Some cached heap objects may hold references to methods in aot-linked -// classes (via MemberName). We need to make sure all classes are -// linked before executing any bytecode. -void AOTLinkedClassBulkLoader::link_classes(JavaThread* current) { - link_classes_impl(current); - if (current->has_pending_exception()) { - exit_on_exception(current); - } -} - -void AOTLinkedClassBulkLoader::link_classes_impl(TRAPS) { - precond(CDSConfig::is_using_aot_linked_classes()); - - AOTLinkedClassTable* table = AOTLinkedClassTable::get(); - - link_classes_in_table(table->boot1(), CHECK); - link_classes_in_table(table->boot2(), CHECK); - link_classes_in_table(table->platform(), CHECK); - link_classes_in_table(table->app(), CHECK); -} - -void AOTLinkedClassBulkLoader::link_classes_in_table(Array* classes, TRAPS) { - if (classes != nullptr) { - for (int i = 0; i < classes->length(); i++) { - // NOTE: CDSConfig::is_preserving_verification_constraints() is required - // when storing ik in the AOT cache. This means we don't have to verify - // ik at all. - // - // Without is_preserving_verification_constraints(), ik->link_class() may cause - // class loading, which may result in invocation of ClassLoader::loadClass() calls, - // which CANNOT happen because we are not ready to execute any Java byecodes yet - // at this point. - InstanceKlass* ik = classes->at(i); - ik->link_class(CHECK); - } - } -} - #ifdef ASSERT void AOTLinkedClassBulkLoader::validate_module_of_preloaded_classes() { oop javabase_module_oop = ModuleEntryTable::javabase_moduleEntry()->module_oop(); @@ -215,21 +173,25 @@ void AOTLinkedClassBulkLoader::validate_module(Klass* k, const char* category_na } #endif -void AOTLinkedClassBulkLoader::init_javabase_classes(JavaThread* current) { - init_classes_for_loader(Handle(), AOTLinkedClassTable::get()->boot1(), current); +// Link all java.base classes in the AOTLinkedClassTable. Of those classes, +// move the ones that have been AOT-initialized to the "initialized" state. +void AOTLinkedClassBulkLoader::link_or_init_javabase_classes(JavaThread* current) { + link_or_init_classes_for_loader(Handle(), AOTLinkedClassTable::get()->boot1(), current); if (current->has_pending_exception()) { exit_on_exception(current); } } -void AOTLinkedClassBulkLoader::init_non_javabase_classes(JavaThread* current) { - init_non_javabase_classes_impl(current); +// Do the same thing as link_or_init_javabase_classes(), but for the classes that are not +// in the java.base module. +void AOTLinkedClassBulkLoader::link_or_init_non_javabase_classes(JavaThread* current) { + link_or_init_non_javabase_classes_impl(current); if (current->has_pending_exception()) { exit_on_exception(current); } } -void AOTLinkedClassBulkLoader::init_non_javabase_classes_impl(TRAPS) { +void AOTLinkedClassBulkLoader::link_or_init_non_javabase_classes_impl(TRAPS) { assert(CDSConfig::is_using_aot_linked_classes(), "sanity"); DEBUG_ONLY(validate_module_of_preloaded_classes()); @@ -246,9 +208,9 @@ void AOTLinkedClassBulkLoader::init_non_javabase_classes_impl(TRAPS) { assert(h_system_loader() != nullptr, "must be"); AOTLinkedClassTable* table = AOTLinkedClassTable::get(); - init_classes_for_loader(Handle(), table->boot2(), CHECK); - init_classes_for_loader(h_platform_loader, table->platform(), CHECK); - init_classes_for_loader(h_system_loader, table->app(), CHECK); + link_or_init_classes_for_loader(Handle(), table->boot2(), CHECK); + link_or_init_classes_for_loader(h_platform_loader, table->platform(), CHECK); + link_or_init_classes_for_loader(h_system_loader, table->app(), CHECK); if (Universe::is_fully_initialized() && VerifyDuringStartup) { // Make sure we're still in a clean state. @@ -280,9 +242,8 @@ void AOTLinkedClassBulkLoader::exit_on_exception(JavaThread* current) { log_error(aot)("Out of memory. Please run with a larger Java heap, current MaxHeapSize = " "%zuM", MaxHeapSize/M); } else { - oop message = java_lang_Throwable::message(current->pending_exception()); log_error(aot)("%s: %s", current->pending_exception()->klass()->external_name(), - message == nullptr ? "(no message)" : java_lang_String::as_utf8_string(message)); + java_lang_String::as_utf8_string(java_lang_Throwable::message(current->pending_exception()))); } vm_exit_during_initialization("Unexpected exception when loading aot-linked classes."); } @@ -328,13 +289,23 @@ void AOTLinkedClassBulkLoader::initiate_loading(JavaThread* current, const char* // - classes that were AOT-initialized by AOTClassInitializer // - the classes of all objects that are reachable from the archived mirrors of // the AOT-linked classes for . -void AOTLinkedClassBulkLoader::init_classes_for_loader(Handle class_loader, Array* classes, TRAPS) { +void AOTLinkedClassBulkLoader::link_or_init_classes_for_loader(Handle class_loader, Array* classes, TRAPS) { if (classes != nullptr) { for (int i = 0; i < classes->length(); i++) { InstanceKlass* ik = classes->at(i); - assert(ik->class_loader_data() != nullptr, "must be"); + if (ik->class_loader_data() == nullptr) { + // This class is not yet loaded. We will initialize it in a later phase. + // For example, we have loaded only AOTLinkedClassCategory::BOOT1 classes + // but k is part of AOTLinkedClassCategory::BOOT2. + continue; + } if (ik->has_aot_initialized_mirror()) { ik->initialize_with_aot_initialized_mirror(CHECK); + } else { + // Some cached heap objects may hold references to methods in aot-linked + // classes (via MemberName). We need to make sure all classes are + // linked to allow such MemberNames to be invoked. + ik->link_class(CHECK); } } } diff --git a/src/hotspot/share/cds/aotLinkedClassBulkLoader.hpp b/src/hotspot/share/cds/aotLinkedClassBulkLoader.hpp index 31fdac386fe51..77400a861040a 100644 --- a/src/hotspot/share/cds/aotLinkedClassBulkLoader.hpp +++ b/src/hotspot/share/cds/aotLinkedClassBulkLoader.hpp @@ -52,11 +52,10 @@ class AOTLinkedClassBulkLoader : AllStatic { static void preload_classes_impl(TRAPS); static void preload_classes_in_table(Array* classes, const char* category_name, Handle loader, TRAPS); - static void initiate_loading(JavaThread* current, const char* category, Handle initiating_loader, Array* classes); - static void link_classes_impl(TRAPS); - static void link_classes_in_table(Array* classes, TRAPS); - static void init_non_javabase_classes_impl(TRAPS); - static void init_classes_for_loader(Handle class_loader, Array* classes, TRAPS); + static void initiate_loading(JavaThread* current, const char* category, Handle initiating_loader, + Array* classes); + static void link_or_init_non_javabase_classes_impl(TRAPS); + static void link_or_init_classes_for_loader(Handle class_loader, Array* classes, TRAPS); static void replay_training_at_init(Array* classes, TRAPS) NOT_CDS_RETURN; #ifdef ASSERT @@ -68,10 +67,9 @@ class AOTLinkedClassBulkLoader : AllStatic { public: static void serialize(SerializeClosure* soc) NOT_CDS_RETURN; - static void preload_classes(JavaThread* current) NOT_CDS_RETURN; - static void link_classes(JavaThread* current) NOT_CDS_RETURN; - static void init_javabase_classes(JavaThread* current) NOT_CDS_RETURN; - static void init_non_javabase_classes(JavaThread* current) NOT_CDS_RETURN; + static void preload_classes(JavaThread* current); + static void link_or_init_javabase_classes(JavaThread* current) NOT_CDS_RETURN; + static void link_or_init_non_javabase_classes(JavaThread* current) NOT_CDS_RETURN; static void exit_on_exception(JavaThread* current); static void replay_training_at_init_for_preloaded_classes(TRAPS) NOT_CDS_RETURN; diff --git a/src/hotspot/share/cds/aotMapLogger.cpp b/src/hotspot/share/cds/aotMapLogger.cpp index 151c15048c28e..b0e410b5cf1bb 100644 --- a/src/hotspot/share/cds/aotMapLogger.cpp +++ b/src/hotspot/share/cds/aotMapLogger.cpp @@ -135,14 +135,12 @@ class AOTMapLogger::RuntimeGatherArchivedMetaspaceObjs : public UniqueMetaspaceC virtual bool do_unique_ref(Ref* ref, bool read_only) { ArchivedObjInfo info; - if (AOTMetaspace::in_aot_cache(ref->obj())) { - info._src_addr = ref->obj(); - info._buffered_addr = ref->obj(); - info._requested_addr = ref->obj(); - info._bytes = ref->size() * BytesPerWord; - info._type = ref->msotype(); - _objs.append(info); - } + info._src_addr = ref->obj(); + info._buffered_addr = ref->obj(); + info._requested_addr = ref->obj(); + info._bytes = ref->size() * BytesPerWord; + info._type = ref->msotype(); + _objs.append(info); return true; // keep iterating } diff --git a/src/hotspot/share/cds/cdsConfig.cpp b/src/hotspot/share/cds/cdsConfig.cpp index a5d1f78b76fa0..7c6b925470a09 100644 --- a/src/hotspot/share/cds/cdsConfig.cpp +++ b/src/hotspot/share/cds/cdsConfig.cpp @@ -943,9 +943,8 @@ bool CDSConfig::is_preserving_verification_constraints() { return AOTClassLinking; } else if (is_dumping_final_static_archive()) { // writing AOT cache return is_dumping_aot_linked_classes(); - } else if (is_dumping_classic_static_archive()) { - return is_dumping_aot_linked_classes(); } else { + // For simplicity, we don't support this optimization with the old CDS workflow. return false; } } diff --git a/src/hotspot/share/cds/finalImageRecipes.cpp b/src/hotspot/share/cds/finalImageRecipes.cpp index a9bbc398736d3..dfe74acd6c1e5 100644 --- a/src/hotspot/share/cds/finalImageRecipes.cpp +++ b/src/hotspot/share/cds/finalImageRecipes.cpp @@ -127,14 +127,6 @@ void FinalImageRecipes::record_recipes_for_constantpool() { } if (cp_indices.length() > 0) { - LogStreamHandle(Trace, aot, resolve) log; - if (log.is_enabled()) { - log.print("ConstantPool entries for %s to be pre-resolved:", k->external_name()); - for (int i = 0; i < cp_indices.length(); i++) { - log.print(" %d", cp_indices.at(i)); - } - log.print("\n"); - } tmp_cp_recipes.append(ArchiveUtils::archive_array(&cp_indices)); } else { tmp_cp_recipes.append(nullptr); diff --git a/src/hotspot/share/cds/runTimeClassInfo.cpp b/src/hotspot/share/cds/runTimeClassInfo.cpp index fe940ca6c183d..832b0ce893223 100644 --- a/src/hotspot/share/cds/runTimeClassInfo.cpp +++ b/src/hotspot/share/cds/runTimeClassInfo.cpp @@ -41,7 +41,7 @@ void RunTimeClassInfo::init(DumpTimeClassInfo& info) { _num_loader_constraints = info.num_loader_constraints(); int i; - if (CDSConfig::is_preserving_verification_constraints()) { + if (CDSConfig::is_preserving_verification_constraints() && CDSConfig::is_dumping_final_static_archive()) { // The production run doesn't need the verifier constraints, as we can guarantee that all classes checked by // the verifier during AOT training/assembly phases cannot be replaced in the production run. _num_verifier_constraints = 0; diff --git a/src/hotspot/share/classfile/stackMapTable.cpp b/src/hotspot/share/classfile/stackMapTable.cpp index 85fb4de868658..9e02956aceb6c 100644 --- a/src/hotspot/share/classfile/stackMapTable.cpp +++ b/src/hotspot/share/classfile/stackMapTable.cpp @@ -132,16 +132,8 @@ bool StackMapTable::match_stackmap( } void StackMapTable::check_jump_target( - StackMapFrame* frame, int bci, int offset, TRAPS) const { + StackMapFrame* frame, int32_t target, TRAPS) const { ErrorContext ctx; - // Jump targets must be within the method and the method size is limited. See JVMS 4.11 - int min_offset = -1 * max_method_code_size; - if (offset < min_offset || offset > max_method_code_size) { - frame->verifier()->verify_error(ErrorContext::bad_stackmap(bci, frame), - "Illegal target of jump or branch (bci %d + offset %d)", bci, offset); - return; - } - int target = bci + offset; bool match = match_stackmap( frame, target, true, false, &ctx, CHECK_VERIFY(frame->verifier())); if (!match || (target < 0 || target >= _code_length)) { diff --git a/src/hotspot/share/classfile/stackMapTable.hpp b/src/hotspot/share/classfile/stackMapTable.hpp index 9b46fa89345d9..6d4c0ce36c086 100644 --- a/src/hotspot/share/classfile/stackMapTable.hpp +++ b/src/hotspot/share/classfile/stackMapTable.hpp @@ -67,7 +67,7 @@ class StackMapTable : public StackObj { // Check jump instructions. Make sure there are no uninitialized // instances on backward branch. - void check_jump_target(StackMapFrame* frame, int bci, int offset, TRAPS) const; + void check_jump_target(StackMapFrame* frame, int32_t target, TRAPS) const; // The following methods are only used inside this class. diff --git a/src/hotspot/share/classfile/systemDictionaryShared.cpp b/src/hotspot/share/classfile/systemDictionaryShared.cpp index cb2ae96348ead..b092e71f4e761 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.cpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp @@ -855,28 +855,6 @@ class UnregisteredClassesDuplicationChecker : StackObj { } }; -void SystemDictionaryShared::link_all_exclusion_check_candidates(InstanceKlass* ik) { - bool need_to_link = false; - { - MutexLocker ml(DumpTimeTable_lock, Mutex::_no_safepoint_check_flag); - ExclusionCheckCandidates candidates(ik); - - candidates.iterate_all([&] (InstanceKlass* k, DumpTimeClassInfo* info) { - if (!k->is_linked()) { - need_to_link = true; - } - }); - } - if (need_to_link) { - JavaThread* THREAD = JavaThread::current(); - if (log_is_enabled(Info, aot, link)) { - ResourceMark rm(THREAD); - log_info(aot, link)("Link all loaded classes for %s", ik->external_name()); - } - AOTMetaspace::link_all_loaded_classes(THREAD); - } -} - // Returns true if the class should be excluded. This can be called by // AOTConstantPoolResolver before or after we enter the CDS safepoint. // When called before the safepoint, we need to link the class so that @@ -900,19 +878,27 @@ bool SystemDictionaryShared::should_be_excluded(Klass* k) { InstanceKlass* ik = InstanceKlass::cast(k); if (!SafepointSynchronize::is_at_safepoint()) { - { - // fast path - MutexLocker ml(DumpTimeTable_lock, Mutex::_no_safepoint_check_flag); - DumpTimeClassInfo* p = get_info_locked(ik); - if (p->has_checked_exclusion()) { - return p->is_excluded(); + if (!ik->is_linked()) { + // should_be_excluded_impl() below doesn't link unlinked classes. We come + // here only when we are trying to aot-link constant pool entries, so + // we'd better link the class. + JavaThread* THREAD = JavaThread::current(); + ik->link_class(THREAD); + if (HAS_PENDING_EXCEPTION) { + CLEAR_PENDING_EXCEPTION; + return true; // linking failed -- let's exclude it } - } - link_all_exclusion_check_candidates(ik); + // Also link any classes that were loaded for the verification of ik or its supertypes. + // Otherwise we might miss the verification constraints of those classes. + AOTMetaspace::link_all_loaded_classes(THREAD); + } MutexLocker ml(DumpTimeTable_lock, Mutex::_no_safepoint_check_flag); DumpTimeClassInfo* p = get_info_locked(ik); + if (p->is_excluded()) { + return true; + } return should_be_excluded_impl(ik, p); } else { // When called within the CDS safepoint, the correctness of this function @@ -926,7 +912,7 @@ bool SystemDictionaryShared::should_be_excluded(Klass* k) { // No need to check for is_linked() as all eligible classes should have // already been linked in AOTMetaspace::link_class_for_cds(). - // Don't take DumpTimeTable_lock as we are in safepoint. + // Can't take the lock as we are in safepoint. DumpTimeClassInfo* p = _dumptime_table->get(ik); if (p->is_excluded()) { return true; @@ -1434,10 +1420,6 @@ void SystemDictionaryShared::get_all_archived_classes(bool is_static_archive, Gr get_archive(is_static_archive)->_builtin_dictionary.iterate([&] (const RunTimeClassInfo* record) { classes->append(record->klass()); }); - - get_archive(is_static_archive)->_unregistered_dictionary.iterate([&] (const RunTimeClassInfo* record) { - classes->append(record->klass()); - }); } class SharedDictionaryPrinter : StackObj { diff --git a/src/hotspot/share/classfile/systemDictionaryShared.hpp b/src/hotspot/share/classfile/systemDictionaryShared.hpp index 2619a642fd1da..5ff57653dd092 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.hpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.hpp @@ -175,7 +175,6 @@ class SystemDictionaryShared: public SystemDictionary { static void write_dictionary(RunTimeSharedDictionary* dictionary, bool is_builtin); static bool is_jfr_event_class(InstanceKlass *k); - static void link_all_exclusion_check_candidates(InstanceKlass* ik); static bool should_be_excluded_impl(InstanceKlass* k, DumpTimeClassInfo* info); // exclusion checks diff --git a/src/hotspot/share/classfile/verifier.cpp b/src/hotspot/share/classfile/verifier.cpp index 38dba1d3d5fbb..9b93e283362fd 100644 --- a/src/hotspot/share/classfile/verifier.cpp +++ b/src/hotspot/share/classfile/verifier.cpp @@ -781,6 +781,7 @@ void ClassVerifier::verify_method(const methodHandle& m, TRAPS) { // Merge with the next instruction { + int target; VerificationType type, type2; VerificationType atype; @@ -1605,8 +1606,9 @@ void ClassVerifier::verify_method(const methodHandle& m, TRAPS) { case Bytecodes::_ifle: current_frame.pop_stack( VerificationType::integer_type(), CHECK_VERIFY(this)); + target = bcs.dest(); stackmap_table.check_jump_target( - ¤t_frame, bcs.bci(), bcs.get_offset_s2(), CHECK_VERIFY(this)); + ¤t_frame, target, CHECK_VERIFY(this)); no_control_flow = false; break; case Bytecodes::_if_acmpeq : case Bytecodes::_if_acmpne : @@ -1617,16 +1619,19 @@ void ClassVerifier::verify_method(const methodHandle& m, TRAPS) { case Bytecodes::_ifnonnull : current_frame.pop_stack( VerificationType::reference_check(), CHECK_VERIFY(this)); + target = bcs.dest(); stackmap_table.check_jump_target - (¤t_frame, bcs.bci(), bcs.get_offset_s2(), CHECK_VERIFY(this)); + (¤t_frame, target, CHECK_VERIFY(this)); no_control_flow = false; break; case Bytecodes::_goto : + target = bcs.dest(); stackmap_table.check_jump_target( - ¤t_frame, bcs.bci(), bcs.get_offset_s2(), CHECK_VERIFY(this)); + ¤t_frame, target, CHECK_VERIFY(this)); no_control_flow = true; break; case Bytecodes::_goto_w : + target = bcs.dest_w(); stackmap_table.check_jump_target( - ¤t_frame, bcs.bci(), bcs.get_offset_s4(), CHECK_VERIFY(this)); + ¤t_frame, target, CHECK_VERIFY(this)); no_control_flow = true; break; case Bytecodes::_tableswitch : case Bytecodes::_lookupswitch : @@ -2275,14 +2280,15 @@ void ClassVerifier::verify_switch( } } } - stackmap_table->check_jump_target(current_frame, bci, default_offset, CHECK_VERIFY(this)); + int target = bci + default_offset; + stackmap_table->check_jump_target(current_frame, target, CHECK_VERIFY(this)); for (int i = 0; i < keys; i++) { // Because check_jump_target() may safepoint, the bytecode could have // moved, which means 'aligned_bcp' is no good and needs to be recalculated. aligned_bcp = align_up(bcs->bcp() + 1, jintSize); - int offset = (jint)Bytes::get_Java_u4(aligned_bcp+(3+i*delta)*jintSize); + target = bci + (jint)Bytes::get_Java_u4(aligned_bcp+(3+i*delta)*jintSize); stackmap_table->check_jump_target( - current_frame, bci, offset, CHECK_VERIFY(this)); + current_frame, target, CHECK_VERIFY(this)); } NOT_PRODUCT(aligned_bcp = nullptr); // no longer valid at this point } diff --git a/src/hotspot/share/classfile/vmIntrinsics.hpp b/src/hotspot/share/classfile/vmIntrinsics.hpp index 0895418ef848b..c9c5c925f86e4 100644 --- a/src/hotspot/share/classfile/vmIntrinsics.hpp +++ b/src/hotspot/share/classfile/vmIntrinsics.hpp @@ -467,8 +467,8 @@ class methodHandle; do_intrinsic(_Reference_clear0, java_lang_ref_Reference, clear0_name, void_method_signature, F_RN) \ do_intrinsic(_PhantomReference_clear0, java_lang_ref_PhantomReference, clear0_name, void_method_signature, F_RN) \ \ - /* support for com.sun.crypto.provider.AES_Crypt and some of its callers */ \ - do_class(com_sun_crypto_provider_aescrypt, "com/sun/crypto/provider/AES_Crypt") \ + /* support for com.sun.crypto.provider.AESCrypt and some of its callers */ \ + do_class(com_sun_crypto_provider_aescrypt, "com/sun/crypto/provider/AESCrypt") \ do_intrinsic(_aescrypt_encryptBlock, com_sun_crypto_provider_aescrypt, encryptBlock_name, byteArray_int_byteArray_int_signature, F_R) \ do_intrinsic(_aescrypt_decryptBlock, com_sun_crypto_provider_aescrypt, decryptBlock_name, byteArray_int_byteArray_int_signature, F_R) \ do_name( encryptBlock_name, "implEncryptBlock") \ diff --git a/src/hotspot/share/code/codeBlob.cpp b/src/hotspot/share/code/codeBlob.cpp index e901d5606161c..18e7752013957 100644 --- a/src/hotspot/share/code/codeBlob.cpp +++ b/src/hotspot/share/code/codeBlob.cpp @@ -910,7 +910,6 @@ void CodeBlob::dump_for_addr(address addr, outputStream* st, bool verbose) const nm->print_nmethod(true); } else { nm->print_on(st); - nm->print_code_snippet(st, addr); } return; } diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp index 8e6a179748039..7274b627f3e6b 100644 --- a/src/hotspot/share/code/nmethod.cpp +++ b/src/hotspot/share/code/nmethod.cpp @@ -23,7 +23,6 @@ */ #include "asm/assembler.inline.hpp" -#include "cds/cdsConfig.hpp" #include "code/codeCache.hpp" #include "code/compiledIC.hpp" #include "code/dependencies.hpp" @@ -1148,7 +1147,7 @@ nmethod* nmethod::new_nmethod(const methodHandle& method, + align_up(speculations_len , oopSize) #endif + align_up(debug_info->data_size() , oopSize) - + ImmutableDataReferencesCounterSize; + + align_up(ImmutableDataReferencesCounterSize, oopSize); // First, allocate space for immutable data in C heap. address immutable_data = nullptr; @@ -1323,7 +1322,6 @@ nmethod::nmethod( #if INCLUDE_JVMCI _speculations_offset = 0; #endif - _immutable_data_reference_counter_offset = 0; code_buffer->copy_code_and_locs_to(this); code_buffer->copy_values_to(this); @@ -1422,6 +1420,15 @@ nmethod::nmethod(const nmethod &nm) : CodeBlob(nm._name, nm._kind, nm._size, nm. _method = nm._method; _osr_link = nullptr; + // Increment number of references to immutable data to share it between nmethods + _immutable_data_size = nm._immutable_data_size; + if (_immutable_data_size > 0) { + _immutable_data = nm._immutable_data; + set_immutable_data_references_counter(get_immutable_data_references_counter() + 1); + } else { + _immutable_data = blob_end(); + } + _exception_cache = nullptr; _gc_data = nullptr; _oops_do_mark_nmethods = nullptr; @@ -1437,7 +1444,6 @@ nmethod::nmethod(const nmethod &nm) : CodeBlob(nm._name, nm._kind, nm._size, nm. _entry_offset = nm._entry_offset; _verified_entry_offset = nm._verified_entry_offset; _entry_bci = nm._entry_bci; - _immutable_data_size = nm._immutable_data_size; _skipped_instructions_size = nm._skipped_instructions_size; _stub_offset = nm._stub_offset; @@ -1456,15 +1462,6 @@ nmethod::nmethod(const nmethod &nm) : CodeBlob(nm._name, nm._kind, nm._size, nm. #if INCLUDE_JVMCI _speculations_offset = nm._speculations_offset; #endif - _immutable_data_reference_counter_offset = nm._immutable_data_reference_counter_offset; - - // Increment number of references to immutable data to share it between nmethods - if (_immutable_data_size > 0) { - _immutable_data = nm._immutable_data; - set_immutable_data_references_counter(get_immutable_data_references_counter() + 1); - } else { - _immutable_data = blob_end(); - } _orig_pc_offset = nm._orig_pc_offset; _compile_id = nm._compile_id; @@ -1754,11 +1751,9 @@ nmethod::nmethod( #if INCLUDE_JVMCI _speculations_offset = _scopes_data_offset + align_up(debug_info->data_size(), oopSize); - _immutable_data_reference_counter_offset = _speculations_offset + align_up(speculations_len, oopSize); - DEBUG_ONLY( int immutable_data_end_offset = _immutable_data_reference_counter_offset + ImmutableDataReferencesCounterSize; ) + DEBUG_ONLY( int immutable_data_end_offset = _speculations_offset + align_up(speculations_len, oopSize) + align_up(ImmutableDataReferencesCounterSize, oopSize); ) #else - _immutable_data_reference_counter_offset = _scopes_data_offset + align_up(debug_info->data_size(), oopSize); - DEBUG_ONLY( int immutable_data_end_offset = _immutable_data_reference_counter_offset + ImmutableDataReferencesCounterSize; ) + DEBUG_ONLY( int immutable_data_end_offset = _scopes_data_offset + align_up(debug_info->data_size(), oopSize) + align_up(ImmutableDataReferencesCounterSize, oopSize); ) #endif assert(immutable_data_end_offset <= immutable_data_size, "wrong read-only data size: %d > %d", immutable_data_end_offset, immutable_data_size); @@ -2505,48 +2500,11 @@ void nmethod::post_compiled_method(CompileTask* task) { maybe_print_nmethod(directive); } -#if INCLUDE_CDS -static GrowableArrayCHeap* _delayed_compiled_method_load_events = nullptr; - -void nmethod::add_delayed_compiled_method_load_event(nmethod* nm) { - precond(CDSConfig::is_using_aot_linked_classes()); - precond(!ServiceThread::has_started()); - - // We are still in single threaded stage of VM bootstrap. No need to lock. - if (_delayed_compiled_method_load_events == nullptr) { - _delayed_compiled_method_load_events = new GrowableArrayCHeap(); - } - _delayed_compiled_method_load_events->append(nm); -} - -void nmethod::post_delayed_compiled_method_load_events() { - precond(ServiceThread::has_started()); - if (_delayed_compiled_method_load_events != nullptr) { - for (int i = 0; i < _delayed_compiled_method_load_events->length(); i++) { - nmethod* nm = _delayed_compiled_method_load_events->at(i); - nm->post_compiled_method_load_event(); - } - delete _delayed_compiled_method_load_events; - _delayed_compiled_method_load_events = nullptr; - } -} -#endif - // ------------------------------------------------------------------ // post_compiled_method_load_event // new method for install_code() path // Transfer information from compilation to jvmti void nmethod::post_compiled_method_load_event(JvmtiThreadState* state) { -#if INCLUDE_CDS - if (!ServiceThread::has_started()) { - // With AOT-linked classes, we could compile wrappers for native methods before the - // ServiceThread has been started, so we must delay the events to be posted later. - assert(state == nullptr, "must be"); - add_delayed_compiled_method_load_event(this); - return; - } -#endif - // This is a bad time for a safepoint. We don't want // this nmethod to get unloaded while we're queueing the event. NoSafepointVerifier nsv; @@ -4308,46 +4266,6 @@ void nmethod::print_value_on_impl(outputStream* st) const { #endif } -void nmethod::print_code_snippet(outputStream* st, address addr) const { - if (entry_point() <= addr && addr < code_end()) { - // Pointing into the nmethod's code. Try to disassemble some instructions around addr. - // Determine conservative start and end points. - address start; - if (frame_complete_offset() != CodeOffsets::frame_never_safe && - addr >= code_begin() + frame_complete_offset()) { - start = code_begin() + frame_complete_offset(); - } else { - start = (addr < verified_entry_point()) ? entry_point() : verified_entry_point(); - } - address start_for_hex_dump = start; // We can choose a different starting point for hex dump, below. - address end = code_end(); - - // Try using relocations to find closer instruction start and end points. - // (Some platforms have variable length instructions and can only - // disassemble correctly at instruction start addresses.) - RelocIterator iter((nmethod*)this, start); - while (iter.next() && iter.addr() < addr) { // find relocation before addr - // Note: There's a relocation which doesn't point to an instruction start: - // ZBarrierRelocationFormatStoreGoodAfterMov with ZGC on x86_64 - // We could detect and skip it, but hex dump is still usable when - // disassembler produces garbage in such a very rare case. - start = iter.addr(); - // We want at least 64 Bytes ahead in hex dump. - if (iter.addr() <= (addr - 64)) start_for_hex_dump = iter.addr(); - } - if (iter.has_current()) { - if (iter.addr() == addr) iter.next(); // find relocation after addr - if (iter.has_current()) end = iter.addr(); - } - - // Always print hex. Disassembler may still have problems when hitting an incorrect instruction start. - os::print_hex_dump(st, start_for_hex_dump, end, 1, /* print_ascii=*/false); - if (!Disassembler::is_abstract()) { - Disassembler::decode(start, end, st); - } - } -} - #ifndef PRODUCT void nmethod::print_calls(outputStream* st) { diff --git a/src/hotspot/share/code/nmethod.hpp b/src/hotspot/share/code/nmethod.hpp index bce0181a3ec6e..2332766a47ce2 100644 --- a/src/hotspot/share/code/nmethod.hpp +++ b/src/hotspot/share/code/nmethod.hpp @@ -250,7 +250,6 @@ class nmethod : public CodeBlob { #if INCLUDE_JVMCI int _speculations_offset; #endif - int _immutable_data_reference_counter_offset; // location in frame (offset for sp) that deopt can store the original // pc during a deopt. @@ -647,11 +646,12 @@ class nmethod : public CodeBlob { #if INCLUDE_JVMCI address scopes_data_end () const { return _immutable_data + _speculations_offset ; } address speculations_begin () const { return _immutable_data + _speculations_offset ; } - address speculations_end () const { return _immutable_data + _immutable_data_reference_counter_offset ; } + address speculations_end () const { return immutable_data_end() - ImmutableDataReferencesCounterSize ; } #else - address scopes_data_end () const { return _immutable_data + _immutable_data_reference_counter_offset ; } + address scopes_data_end () const { return immutable_data_end() - ImmutableDataReferencesCounterSize ; } #endif - address immutable_data_references_counter_begin () const { return _immutable_data + _immutable_data_reference_counter_offset ; } + + address immutable_data_references_counter_begin () const { return immutable_data_end() - ImmutableDataReferencesCounterSize ; } // Sizes int immutable_data_size() const { return _immutable_data_size; } @@ -965,8 +965,6 @@ class nmethod : public CodeBlob { inline int get_immutable_data_references_counter() { return *((int*)immutable_data_references_counter_begin()); } inline void set_immutable_data_references_counter(int count) { *((int*)immutable_data_references_counter_begin()) = count; } - static void add_delayed_compiled_method_load_event(nmethod* nm) NOT_CDS_RETURN; - public: // ScopeDesc retrieval operation PcDesc* pc_desc_at(address pc) { return find_pc_desc(pc, false); } @@ -1001,14 +999,10 @@ class nmethod : public CodeBlob { // Avoid hiding of parent's 'decode(outputStream*)' method. void decode(outputStream* st) const { decode2(st); } // just delegate here. - // AOT cache support - static void post_delayed_compiled_method_load_events() NOT_CDS_RETURN; - // printing support void print_on_impl(outputStream* st) const; void print_code(); void print_value_on_impl(outputStream* st) const; - void print_code_snippet(outputStream* st, address addr) const; #if defined(SUPPORT_DATA_STRUCTS) // print output in opt build for disassembler library diff --git a/src/hotspot/share/compiler/compilerDefinitions.cpp b/src/hotspot/share/compiler/compilerDefinitions.cpp index aed1edc0db5f6..35201973dfe77 100644 --- a/src/hotspot/share/compiler/compilerDefinitions.cpp +++ b/src/hotspot/share/compiler/compilerDefinitions.cpp @@ -215,6 +215,11 @@ void CompilerConfig::set_client_emulation_mode_flags() { if (FLAG_IS_DEFAULT(CodeCacheExpansionSize)) { FLAG_SET_ERGO(CodeCacheExpansionSize, 32*K); } + if (FLAG_IS_DEFAULT(MaxRAM)) { + // Do not use FLAG_SET_ERGO to update MaxRAM, as this will impact + // heap setting done based on available phys_mem (see Arguments::set_heap_size). + FLAG_SET_DEFAULT(MaxRAM, 1ULL*G); + } if (FLAG_IS_DEFAULT(CICompilerCount)) { FLAG_SET_ERGO(CICompilerCount, 1); } @@ -548,36 +553,21 @@ bool CompilerConfig::check_args_consistency(bool status) { return status; } -bool CompilerConfig::should_set_client_emulation_mode_flags() { +void CompilerConfig::ergo_initialize() { #if !COMPILER1_OR_COMPILER2 - return false; + return; #endif if (has_c1()) { if (!is_compilation_mode_selected()) { if (NeverActAsServerClassMachine) { - return true; + set_client_emulation_mode_flags(); } } else if (!has_c2() && !is_jvmci_compiler()) { - return true; + set_client_emulation_mode_flags(); } } - return false; -} - -void CompilerConfig::ergo_initialize() { -#if !COMPILER1_OR_COMPILER2 - return; -#endif - - // This property is also checked when selecting the heap size. Since client - // emulation mode influences Java heap memory usage, part of the logic must - // occur before choosing the heap size. - if (should_set_client_emulation_mode_flags()) { - set_client_emulation_mode_flags(); - } - set_legacy_emulation_flags(); set_compilation_policy_flags(); diff --git a/src/hotspot/share/compiler/compilerDefinitions.hpp b/src/hotspot/share/compiler/compilerDefinitions.hpp index a9b052ff78231..1c8c65b2a533d 100644 --- a/src/hotspot/share/compiler/compilerDefinitions.hpp +++ b/src/hotspot/share/compiler/compilerDefinitions.hpp @@ -151,8 +151,6 @@ class CompilerConfig : public AllStatic { inline static CompilerType compiler_type(); - static bool should_set_client_emulation_mode_flags(); - private: static bool is_compilation_mode_selected(); static void set_compilation_policy_flags(); diff --git a/src/hotspot/share/compiler/compilerOracle.cpp b/src/hotspot/share/compiler/compilerOracle.cpp index 23bb754f43244..868ae8bfa41f4 100644 --- a/src/hotspot/share/compiler/compilerOracle.cpp +++ b/src/hotspot/share/compiler/compilerOracle.cpp @@ -617,44 +617,18 @@ static void usage() { tty->cr(); print_commands(); tty->cr(); - tty->print_cr("The has the format '.'."); - tty->cr(); - tty->print_cr("For example, the "); - tty->cr(); - tty->print_cr(" package/Class.method(Lpackage/Parameter;)Lpackage/Return;"); - tty->cr(); - tty->print_cr("matches the 'method' in 'package/Class' with "); - tty->print_cr("'(Lpackage/Parameter;)Lpackage/Return;'"); + tty->print_cr("Method patterns has the format:"); + tty->print_cr(" package/Class.method()"); tty->cr(); tty->print_cr("For backward compatibility this form is also allowed:"); + tty->print_cr(" package.Class::method()"); tty->cr(); - tty->print_cr(" package.Class::method(Lpackage.Parameter;)Lpackage.Return;"); - tty->cr(); - tty->print_cr("A whitespace or comma can optionally separate the from the"); - tty->print_cr(":"); - tty->cr(); - tty->print_cr(" package/Class.method (Lpackage/Parameter;)Lpackage/Return;"); - tty->print_cr(" package/Class.method,(Lpackage/Parameter;)Lpackage/Return;"); - tty->cr(); - tty->print_cr("The and accept leading and trailing '*' wildcards"); - tty->print_cr("matching:"); - tty->cr(); - tty->print_cr(" *ackage/Clas*.*etho*(Lpackage/Parameter;)Lpackage/Return;"); - tty->cr(); - tty->print_cr("The does not support explicit wildcards and"); - tty->print_cr("always has an implicit trailing wildcard. Therefore,"); - tty->cr(); - tty->print_cr(" package/Class.method(Lpackage/Parameter;)Lpackage/Return;"); - tty->cr(); - tty->print_cr("matches a subset of"); - tty->cr(); - tty->print_cr(" package/Class.method(Lpackage/Parameter;)"); - tty->cr(); - tty->print_cr("which matches a subset of"); - tty->cr(); - tty->print_cr(" package/Class.method"); + tty->print_cr("The signature can be separated by an optional whitespace or comma:"); + tty->print_cr(" package/Class.method ()"); tty->cr(); - tty->print_cr("which matches all possible descriptors."); + tty->print_cr("The class and method identifier can be used together with leading or"); + tty->print_cr("trailing *'s for wildcard matching:"); + tty->print_cr(" *ackage/Clas*.*etho*()"); tty->cr(); tty->print_cr("It is possible to use more than one CompileCommand on the command line:"); tty->print_cr(" -XX:CompileCommand=exclude,java/*.* -XX:CompileCommand=log,java*.*"); diff --git a/src/hotspot/share/gc/epsilon/epsilonHeap.cpp b/src/hotspot/share/gc/epsilon/epsilonHeap.cpp index f3d411e34ba51..16cae714cb976 100644 --- a/src/hotspot/share/gc/epsilon/epsilonHeap.cpp +++ b/src/hotspot/share/gc/epsilon/epsilonHeap.cpp @@ -52,7 +52,7 @@ jint EpsilonHeap::initialize() { initialize_reserved_region(heap_rs); _space = new ContiguousSpace(); - _space->initialize(committed_region, /* clear_space = */ true); + _space->initialize(committed_region, /* clear_space = */ true, /* mangle_space = */ true); // Precompute hot fields _max_tlab_size = MIN2(CollectedHeap::max_tlab_size(), align_object_size(EpsilonMaxTLABSize / HeapWordSize)); diff --git a/src/hotspot/share/gc/g1/g1BarrierSet.cpp b/src/hotspot/share/gc/g1/g1BarrierSet.cpp index 622651ce0d8d1..ab7d6febf4cf7 100644 --- a/src/hotspot/share/gc/g1/g1BarrierSet.cpp +++ b/src/hotspot/share/gc/g1/g1BarrierSet.cpp @@ -111,7 +111,7 @@ void G1BarrierSet::write_ref_array_pre(narrowOop* dst, size_t count, bool dest_u } } -void G1BarrierSet::write_region(MemRegion mr) { +void G1BarrierSet::write_region(JavaThread* thread, MemRegion mr) { if (mr.is_empty()) { return; } diff --git a/src/hotspot/share/gc/g1/g1BarrierSet.hpp b/src/hotspot/share/gc/g1/g1BarrierSet.hpp index 58a70ed6a6076..20642cfc7e6c1 100644 --- a/src/hotspot/share/gc/g1/g1BarrierSet.hpp +++ b/src/hotspot/share/gc/g1/g1BarrierSet.hpp @@ -84,6 +84,10 @@ class G1BarrierSet: public CardTableBarrierSet { // Update the given thread's card table (byte map) base to the current card table's. void update_card_table_base(Thread* thread); + virtual bool card_mark_must_follow_store() const { + return true; + } + // Add "pre_val" to a set of objects that may have been disconnected from the // pre-marking object graph. Prefer the version that takes location, as it // can avoid touching the heap unnecessarily. @@ -99,7 +103,8 @@ class G1BarrierSet: public CardTableBarrierSet { template void write_ref_field_pre(T* field); - virtual void write_region(MemRegion mr); + inline void write_region(MemRegion mr); + void write_region(JavaThread* thread, MemRegion mr); template void write_ref_field_post(T* field); diff --git a/src/hotspot/share/gc/g1/g1BarrierSet.inline.hpp b/src/hotspot/share/gc/g1/g1BarrierSet.inline.hpp index ffba561f11f3d..0888fc589375a 100644 --- a/src/hotspot/share/gc/g1/g1BarrierSet.inline.hpp +++ b/src/hotspot/share/gc/g1/g1BarrierSet.inline.hpp @@ -68,6 +68,10 @@ inline void G1BarrierSet::write_ref_field_pre(T* field) { enqueue(field); } +inline void G1BarrierSet::write_region(MemRegion mr) { + write_region(JavaThread::current(), mr); +} + template inline void G1BarrierSet::write_ref_field_post(T* field) { volatile CardValue* byte = _card_table->byte_for(field); diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index d3e02df3e09b6..c1b18a71cfbfd 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -403,25 +403,21 @@ HeapWord* G1CollectedHeap::allocate_new_tlab(size_t min_size, assert_heap_not_locked_and_not_at_safepoint(); assert(!is_humongous(requested_size), "we do not allow humongous TLABs"); - // Do not allow a GC because we are allocating a new TLAB to avoid an issue - // with UseGCOverheadLimit: although this GC would return null if the overhead - // limit would be exceeded, but it would likely free at least some space. - // So the subsequent outside-TLAB allocation could be successful anyway and - // the indication that the overhead limit had been exceeded swallowed. - return attempt_allocation(min_size, requested_size, actual_size, false /* allow_gc */); + return attempt_allocation(min_size, requested_size, actual_size); } -HeapWord* G1CollectedHeap::mem_allocate(size_t word_size) { +HeapWord* +G1CollectedHeap::mem_allocate(size_t word_size) { assert_heap_not_locked_and_not_at_safepoint(); if (is_humongous(word_size)) { return attempt_allocation_humongous(word_size); } size_t dummy = 0; - return attempt_allocation(word_size, word_size, &dummy, true /* allow_gc */); + return attempt_allocation(word_size, word_size, &dummy); } -HeapWord* G1CollectedHeap::attempt_allocation_slow(uint node_index, size_t word_size, bool allow_gc) { +HeapWord* G1CollectedHeap::attempt_allocation_slow(uint node_index, size_t word_size) { ResourceMark rm; // For retrieving the thread names in log messages. // Make sure you read the note in attempt_allocation_humongous(). @@ -448,8 +444,6 @@ HeapWord* G1CollectedHeap::attempt_allocation_slow(uint node_index, size_t word_ result = _allocator->attempt_allocation_locked(node_index, word_size); if (result != nullptr) { return result; - } else if (!allow_gc) { - return nullptr; } // Read the GC count while still holding the Heap_lock. @@ -618,8 +612,7 @@ void G1CollectedHeap::dealloc_archive_regions(MemRegion range) { inline HeapWord* G1CollectedHeap::attempt_allocation(size_t min_word_size, size_t desired_word_size, - size_t* actual_word_size, - bool allow_gc) { + size_t* actual_word_size) { assert_heap_not_locked_and_not_at_safepoint(); assert(!is_humongous(desired_word_size), "attempt_allocation() should not " "be called for humongous allocation requests"); @@ -631,7 +624,7 @@ inline HeapWord* G1CollectedHeap::attempt_allocation(size_t min_word_size, if (result == nullptr) { *actual_word_size = desired_word_size; - result = attempt_allocation_slow(node_index, desired_word_size, allow_gc); + result = attempt_allocation_slow(node_index, desired_word_size); } assert_heap_not_locked(); @@ -1398,6 +1391,7 @@ jint G1CollectedHeap::initialize() { G1CardTable* refinement_table = new G1CardTable(_reserved); G1BarrierSet* bs = new G1BarrierSet(card_table, refinement_table); + bs->initialize(); assert(bs->is_a(BarrierSet::G1BarrierSet), "sanity"); // Create space mappers. diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp index 0d354525d89da..7e3f8a3028568 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp @@ -439,14 +439,18 @@ class G1CollectedHeap : public CollectedHeap { // // * If either call cannot satisfy the allocation request using the // current allocating region, they will try to get a new one. If - // this fails, (only) mem_allocate() will attempt to do an evacuation - // pause and retry the allocation. Allocate_new_tlab() will return null, - // deferring to the following mem_allocate(). + // this fails, they will attempt to do an evacuation pause and + // retry the allocation. + // + // * If all allocation attempts fail, even after trying to schedule + // an evacuation pause, allocate_new_tlab() will return null, + // whereas mem_allocate() will attempt a heap expansion and/or + // schedule a Full GC. // // * We do not allow humongous-sized TLABs. So, allocate_new_tlab // should never be called with word_size being humongous. All // humongous allocation requests should go to mem_allocate() which - // will satisfy them in a special path. + // will satisfy them with a special path. HeapWord* allocate_new_tlab(size_t min_size, size_t requested_size, @@ -459,13 +463,12 @@ class G1CollectedHeap : public CollectedHeap { // should only be used for non-humongous allocations. inline HeapWord* attempt_allocation(size_t min_word_size, size_t desired_word_size, - size_t* actual_word_size, - bool allow_gc); + size_t* actual_word_size); + // Second-level mutator allocation attempt: take the Heap_lock and // retry the allocation attempt, potentially scheduling a GC - // pause if allow_gc is set. This should only be used for non-humongous - // allocations. - HeapWord* attempt_allocation_slow(uint node_index, size_t word_size, bool allow_gc); + // pause. This should only be used for non-humongous allocations. + HeapWord* attempt_allocation_slow(uint node_index, size_t word_size); // Takes the Heap_lock and attempts a humongous allocation. It can // potentially schedule a GC pause. diff --git a/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp b/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp index 36412ce5efe95..df4312ebd7554 100644 --- a/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp +++ b/src/hotspot/share/gc/parallel/mutableNUMASpace.cpp @@ -37,11 +37,21 @@ #include "runtime/threadSMR.hpp" #include "utilities/align.hpp" -MutableNUMASpace::MutableNUMASpace(size_t page_size) : MutableSpace(page_size) { +MutableNUMASpace::MutableNUMASpace(size_t alignment) : MutableSpace(alignment), _must_use_large_pages(false) { _lgrp_spaces = new (mtGC) GrowableArray(0, mtGC); + _page_size = os::vm_page_size(); _adaptation_cycles = 0; _samples_count = 0; +#ifdef LINUX + // Changing the page size can lead to freeing of memory. When using large pages + // and the memory has been both reserved and committed, Linux does not support + // freeing parts of it. + if (UseLargePages && !os::can_commit_large_page_memory()) { + _must_use_large_pages = true; + } +#endif // LINUX + size_t lgrp_limit = os::numa_get_groups_num(); uint *lgrp_ids = NEW_C_HEAP_ARRAY(uint, lgrp_limit, mtGC); size_t lgrp_num = os::numa_get_leaf_groups(lgrp_ids, lgrp_limit); @@ -50,7 +60,7 @@ MutableNUMASpace::MutableNUMASpace(size_t page_size) : MutableSpace(page_size) { lgrp_spaces()->reserve(checked_cast(lgrp_num)); // Add new spaces for the new nodes for (size_t i = 0; i < lgrp_num; i++) { - lgrp_spaces()->append(new LGRPSpace(lgrp_ids[i], page_size)); + lgrp_spaces()->append(new LGRPSpace(lgrp_ids[i], alignment)); } FREE_C_HEAP_ARRAY(uint, lgrp_ids); @@ -118,10 +128,7 @@ MutableNUMASpace::LGRPSpace *MutableNUMASpace::lgrp_space_for_thread(Thread* thr return space->lgrp_id() == (uint)lgrp_id; }); - if (lgrp_spaces_index == -1) { - // Running on a CPU with no memory; pick another CPU based on %. - lgrp_spaces_index = lgrp_id % lgrp_spaces()->length(); - } + assert(lgrp_spaces_index != -1, "must have created spaces for all lgrp_ids"); return lgrp_spaces()->at(lgrp_spaces_index); } @@ -139,19 +146,22 @@ size_t MutableNUMASpace::unsafe_max_tlab_alloc(Thread *thr) const { // Bias region towards the first-touching lgrp. Set the right page sizes. void MutableNUMASpace::bias_region(MemRegion mr, uint lgrp_id) { - assert(is_aligned(mr.start(), page_size()), "precondition"); - assert(is_aligned(mr.end(), page_size()), "precondition"); - - if (mr.is_empty()) { - return; + HeapWord *start = align_up(mr.start(), page_size()); + HeapWord *end = align_down(mr.end(), page_size()); + if (end > start) { + MemRegion aligned_region(start, end); + assert((intptr_t)aligned_region.start() % page_size() == 0 && + (intptr_t)aligned_region.byte_size() % page_size() == 0, "Bad alignment"); + assert(region().contains(aligned_region), "Sanity"); + // First we tell the OS which page size we want in the given range. The underlying + // large page can be broken down if we require small pages. + const size_t os_align = UseLargePages ? page_size() : os::vm_page_size(); + os::realign_memory((char*)aligned_region.start(), aligned_region.byte_size(), os_align); + // Then we uncommit the pages in the range. + os::disclaim_memory((char*)aligned_region.start(), aligned_region.byte_size()); + // And make them local/first-touch biased. + os::numa_make_local((char*)aligned_region.start(), aligned_region.byte_size(), checked_cast(lgrp_id)); } - // First we tell the OS which page size we want in the given range. The underlying - // large page can be broken down if we require small pages. - os::realign_memory((char*) mr.start(), mr.byte_size(), page_size()); - // Then we uncommit the pages in the range. - os::disclaim_memory((char*) mr.start(), mr.byte_size()); - // And make them local/first-touch biased. - os::numa_make_local((char*)mr.start(), mr.byte_size(), checked_cast(lgrp_id)); } // Update space layout. Perform adaptation. @@ -200,15 +210,14 @@ size_t MutableNUMASpace::current_chunk_size(int i) { // Return the default chunk size by equally diving the space. // page_size() aligned. size_t MutableNUMASpace::default_chunk_size() { - // The number of pages may not be evenly divided. - return align_down(capacity_in_bytes() / lgrp_spaces()->length(), page_size()); + return base_space_size() / lgrp_spaces()->length() * page_size(); } // Produce a new chunk size. page_size() aligned. // This function is expected to be called on sequence of i's from 0 to // lgrp_spaces()->length(). size_t MutableNUMASpace::adaptive_chunk_size(int i, size_t limit) { - size_t pages_available = capacity_in_bytes() / page_size(); + size_t pages_available = base_space_size(); for (int j = 0; j < i; j++) { pages_available -= align_down(current_chunk_size(j), page_size()) / page_size(); } @@ -254,13 +263,20 @@ size_t MutableNUMASpace::adaptive_chunk_size(int i, size_t limit) { // |----bottom_region--|---intersection---|------top_region------| void MutableNUMASpace::select_tails(MemRegion new_region, MemRegion intersection, MemRegion* bottom_region, MemRegion *top_region) { - assert(is_aligned(new_region.start(), page_size()), "precondition"); - assert(is_aligned(new_region.end(), page_size()), "precondition"); - assert(is_aligned(intersection.start(), page_size()), "precondition"); - assert(is_aligned(intersection.end(), page_size()), "precondition"); - // Is there bottom? if (new_region.start() < intersection.start()) { // Yes + // Try to coalesce small pages into a large one. + if (UseLargePages && page_size() >= alignment()) { + HeapWord* p = align_up(intersection.start(), alignment()); + if (new_region.contains(p) + && pointer_delta(p, new_region.start(), sizeof(char)) >= alignment()) { + if (intersection.contains(p)) { + intersection = MemRegion(p, intersection.end()); + } else { + intersection = MemRegion(p, p); + } + } + } *bottom_region = MemRegion(new_region.start(), intersection.start()); } else { *bottom_region = MemRegion(); @@ -268,6 +284,18 @@ void MutableNUMASpace::select_tails(MemRegion new_region, MemRegion intersection // Is there top? if (intersection.end() < new_region.end()) { // Yes + // Try to coalesce small pages into a large one. + if (UseLargePages && page_size() >= alignment()) { + HeapWord* p = align_down(intersection.end(), alignment()); + if (new_region.contains(p) + && pointer_delta(new_region.end(), p, sizeof(char)) >= alignment()) { + if (intersection.contains(p)) { + intersection = MemRegion(intersection.start(), p); + } else { + intersection = MemRegion(p, p); + } + } + } *top_region = MemRegion(intersection.end(), new_region.end()); } else { *top_region = MemRegion(); @@ -281,8 +309,6 @@ void MutableNUMASpace::initialize(MemRegion mr, WorkerThreads* pretouch_workers) { assert(clear_space, "Reallocation will destroy data!"); assert(lgrp_spaces()->length() > 0, "There should be at least one space"); - assert(is_aligned(mr.start(), page_size()), "precondition"); - assert(is_aligned(mr.end(), page_size()), "precondition"); MemRegion old_region = region(), new_region; set_bottom(mr.start()); @@ -290,22 +316,37 @@ void MutableNUMASpace::initialize(MemRegion mr, // Must always clear the space clear(SpaceDecorator::DontMangle); - size_t num_pages = mr.byte_size() / page_size(); - - if (num_pages < (size_t)lgrp_spaces()->length()) { - log_warning(gc)("Degraded NUMA config: #os-pages (%zu) < #CPU (%d); space-size: %zu, page-size: %zu", - num_pages, lgrp_spaces()->length(), mr.byte_size(), page_size()); - - // Keep only the first few CPUs. - lgrp_spaces()->trunc_to((int)num_pages); + // Compute chunk sizes + size_t prev_page_size = page_size(); + set_page_size(alignment()); + HeapWord* rounded_bottom = align_up(bottom(), page_size()); + HeapWord* rounded_end = align_down(end(), page_size()); + size_t base_space_size_pages = pointer_delta(rounded_end, rounded_bottom, sizeof(char)) / page_size(); + + // Try small pages if the chunk size is too small + if (base_space_size_pages / lgrp_spaces()->length() == 0 + && page_size() > os::vm_page_size()) { + // Changing the page size below can lead to freeing of memory. So we fail initialization. + if (_must_use_large_pages) { + vm_exit_during_initialization("Failed initializing NUMA with large pages. Too small heap size"); + } + set_page_size(os::vm_page_size()); + rounded_bottom = align_up(bottom(), page_size()); + rounded_end = align_down(end(), page_size()); + base_space_size_pages = pointer_delta(rounded_end, rounded_bottom, sizeof(char)) / page_size(); } + guarantee(base_space_size_pages / lgrp_spaces()->length() > 0, "Space too small"); + set_base_space_size(base_space_size_pages); // Handle space resize MemRegion top_region, bottom_region; if (!old_region.equals(region())) { - new_region = mr; + new_region = MemRegion(rounded_bottom, rounded_end); MemRegion intersection = new_region.intersection(old_region); - if (intersection.is_empty()) { + if (intersection.start() == nullptr || + intersection.end() == nullptr || + prev_page_size > page_size()) { // If the page size got smaller we have to change + // the page size preference for the whole space. intersection = MemRegion(new_region.start(), new_region.start()); } select_tails(new_region, intersection, &bottom_region, &top_region); @@ -352,18 +393,19 @@ void MutableNUMASpace::initialize(MemRegion mr, if (i == 0) { // Bottom chunk if (i != lgrp_spaces()->length() - 1) { - new_region = MemRegion(bottom(), chunk_byte_size >> LogHeapWordSize); + new_region = MemRegion(bottom(), rounded_bottom + (chunk_byte_size >> LogHeapWordSize)); } else { new_region = MemRegion(bottom(), end()); } - } else if (i < lgrp_spaces()->length() - 1) { // Middle chunks - MutableSpace* ps = lgrp_spaces()->at(i - 1)->space(); - new_region = MemRegion(ps->end(), - chunk_byte_size >> LogHeapWordSize); - } else { // Top chunk - MutableSpace* ps = lgrp_spaces()->at(i - 1)->space(); - new_region = MemRegion(ps->end(), end()); - } + } else + if (i < lgrp_spaces()->length() - 1) { // Middle chunks + MutableSpace *ps = lgrp_spaces()->at(i - 1)->space(); + new_region = MemRegion(ps->end(), + ps->end() + (chunk_byte_size >> LogHeapWordSize)); + } else { // Top chunk + MutableSpace *ps = lgrp_spaces()->at(i - 1)->space(); + new_region = MemRegion(ps->end(), end()); + } guarantee(region().contains(new_region), "Region invariant"); @@ -390,8 +432,9 @@ void MutableNUMASpace::initialize(MemRegion mr, // Clear space (set top = bottom) but never mangle. s->initialize(new_region, SpaceDecorator::Clear, SpaceDecorator::DontMangle, MutableSpace::DontSetupPages); + + set_adaptation_cycles(samples_count()); } - set_adaptation_cycles(samples_count()); } // Set the top of the whole space. diff --git a/src/hotspot/share/gc/parallel/mutableNUMASpace.hpp b/src/hotspot/share/gc/parallel/mutableNUMASpace.hpp index 0285037659268..dc37b10292ad6 100644 --- a/src/hotspot/share/gc/parallel/mutableNUMASpace.hpp +++ b/src/hotspot/share/gc/parallel/mutableNUMASpace.hpp @@ -80,8 +80,8 @@ class MutableNUMASpace : public MutableSpace { SpaceStats _space_stats; public: - LGRPSpace(uint l, size_t page_size) : _lgrp_id(l), _allocation_failed(false) { - _space = new MutableSpace(page_size); + LGRPSpace(uint l, size_t alignment) : _lgrp_id(l), _allocation_failed(false) { + _space = new MutableSpace(alignment); _alloc_rate = new AdaptiveWeightedAverage(NUMAChunkResizeWeight); } ~LGRPSpace() { @@ -117,14 +117,24 @@ class MutableNUMASpace : public MutableSpace { }; GrowableArray* _lgrp_spaces; + size_t _page_size; unsigned _adaptation_cycles, _samples_count; + bool _must_use_large_pages; + + void set_page_size(size_t psz) { _page_size = psz; } + size_t page_size() const { return _page_size; } + unsigned adaptation_cycles() { return _adaptation_cycles; } void set_adaptation_cycles(int v) { _adaptation_cycles = v; } unsigned samples_count() { return _samples_count; } void increment_samples_count() { ++_samples_count; } + size_t _base_space_size; + void set_base_space_size(size_t v) { _base_space_size = v; } + size_t base_space_size() const { return _base_space_size; } + // Bias region towards the lgrp. void bias_region(MemRegion mr, uint lgrp_id); @@ -144,7 +154,7 @@ class MutableNUMASpace : public MutableSpace { public: GrowableArray* lgrp_spaces() const { return _lgrp_spaces; } - MutableNUMASpace(size_t page_size); + MutableNUMASpace(size_t alignment); virtual ~MutableNUMASpace(); // Space initialization. virtual void initialize(MemRegion mr, diff --git a/src/hotspot/share/gc/parallel/mutableSpace.cpp b/src/hotspot/share/gc/parallel/mutableSpace.cpp index a8f47a387e35b..71fddf2c4dad9 100644 --- a/src/hotspot/share/gc/parallel/mutableSpace.cpp +++ b/src/hotspot/share/gc/parallel/mutableSpace.cpp @@ -34,26 +34,30 @@ #include "utilities/align.hpp" #include "utilities/macros.hpp" -MutableSpace::MutableSpace(size_t page_size) : +MutableSpace::MutableSpace(size_t alignment) : _last_setup_region(), - _page_size(page_size), + _alignment(alignment), _bottom(nullptr), _top(nullptr), - _end(nullptr) {} - -void MutableSpace::numa_setup_pages(MemRegion mr, bool clear_space) { - assert(is_aligned(mr.start(), page_size()), "precondition"); - assert(is_aligned(mr.end(), page_size()), "precondition"); - - if (mr.is_empty()) { - return; - } + _end(nullptr) +{ + assert(MutableSpace::alignment() % os::vm_page_size() == 0, + "Space should be aligned"); +} - if (clear_space) { - // Prefer page reallocation to migration. - os::disclaim_memory((char*) mr.start(), mr.byte_size()); +void MutableSpace::numa_setup_pages(MemRegion mr, size_t page_size, bool clear_space) { + if (!mr.is_empty()) { + HeapWord *start = align_up(mr.start(), page_size); + HeapWord *end = align_down(mr.end(), page_size); + if (end > start) { + size_t size = pointer_delta(end, start, sizeof(char)); + if (clear_space) { + // Prefer page reallocation to migration. + os::disclaim_memory((char*)start, size); + } + os::numa_make_global((char*)start, size); + } } - os::numa_make_global((char*) mr.start(), mr.byte_size()); } void MutableSpace::initialize(MemRegion mr, @@ -101,17 +105,20 @@ void MutableSpace::initialize(MemRegion mr, } assert(mr.contains(head) && mr.contains(tail), "Sanity"); + size_t page_size = alignment(); + if (UseNUMA) { - numa_setup_pages(head, clear_space); - numa_setup_pages(tail, clear_space); + numa_setup_pages(head, page_size, clear_space); + numa_setup_pages(tail, page_size, clear_space); } if (AlwaysPreTouch) { + size_t pretouch_page_size = UseLargePages ? page_size : os::vm_page_size(); PretouchTask::pretouch("ParallelGC PreTouch head", (char*)head.start(), (char*)head.end(), - page_size(), pretouch_workers); + pretouch_page_size, pretouch_workers); PretouchTask::pretouch("ParallelGC PreTouch tail", (char*)tail.start(), (char*)tail.end(), - page_size(), pretouch_workers); + pretouch_page_size, pretouch_workers); } // Remember where we stopped so that we can continue later. diff --git a/src/hotspot/share/gc/parallel/mutableSpace.hpp b/src/hotspot/share/gc/parallel/mutableSpace.hpp index 785bfe272287a..d09a2b2df89b7 100644 --- a/src/hotspot/share/gc/parallel/mutableSpace.hpp +++ b/src/hotspot/share/gc/parallel/mutableSpace.hpp @@ -51,20 +51,17 @@ class MutableSpace: public CHeapObj { // The last region which page had been setup to be interleaved. MemRegion _last_setup_region; - size_t _page_size; + size_t _alignment; HeapWord* _bottom; HeapWord* volatile _top; HeapWord* _end; - void numa_setup_pages(MemRegion mr, bool clear_space); + void numa_setup_pages(MemRegion mr, size_t page_size, bool clear_space); void set_last_setup_region(MemRegion mr) { _last_setup_region = mr; } MemRegion last_setup_region() const { return _last_setup_region; } -protected: - size_t page_size() const { return _page_size; } - -public: + public: virtual ~MutableSpace() = default; MutableSpace(size_t page_size); @@ -80,6 +77,8 @@ class MutableSpace: public CHeapObj { HeapWord* volatile* top_addr() { return &_top; } HeapWord** end_addr() { return &_end; } + size_t alignment() { return _alignment; } + MemRegion region() const { return MemRegion(bottom(), end()); } size_t capacity_in_bytes() const { return capacity_in_words() * HeapWordSize; } diff --git a/src/hotspot/share/gc/parallel/objectStartArray.cpp b/src/hotspot/share/gc/parallel/objectStartArray.cpp index 255ee0c56ec42..d120c71d2fa2c 100644 --- a/src/hotspot/share/gc/parallel/objectStartArray.cpp +++ b/src/hotspot/share/gc/parallel/objectStartArray.cpp @@ -47,10 +47,7 @@ ObjectStartArray::ObjectStartArray(MemRegion covered_region) // Do not use large-pages for the backing store. The one large page region // will be used for the heap proper. - ReservedSpace backing_store = MemoryReserver::reserve(bytes_to_reserve, - os::vm_allocation_granularity(), - os::vm_page_size(), - mtGC); + ReservedSpace backing_store = MemoryReserver::reserve(bytes_to_reserve, mtGC); if (!backing_store.is_reserved()) { vm_exit_during_initialization("Could not reserve space for ObjectStartArray"); } diff --git a/src/hotspot/share/gc/parallel/parallelArguments.cpp b/src/hotspot/share/gc/parallel/parallelArguments.cpp index 2d267951f797a..780185952b4cb 100644 --- a/src/hotspot/share/gc/parallel/parallelArguments.cpp +++ b/src/hotspot/share/gc/parallel/parallelArguments.cpp @@ -103,10 +103,15 @@ void ParallelArguments::initialize() { FullGCForwarding::initialize_flags(heap_reserved_size_bytes()); } +// The alignment used for spaces in young gen and old gen +static size_t default_space_alignment() { + return 64 * K * HeapWordSize; +} + void ParallelArguments::initialize_alignments() { // Initialize card size before initializing alignments CardTable::initialize_card_size(); - SpaceAlignment = ParallelScavengeHeap::default_space_alignment(); + SpaceAlignment = default_space_alignment(); HeapAlignment = compute_heap_alignment(); } @@ -118,23 +123,12 @@ void ParallelArguments::initialize_heap_flags_and_sizes_one_pass() { void ParallelArguments::initialize_heap_flags_and_sizes() { initialize_heap_flags_and_sizes_one_pass(); - if (!UseLargePages) { - ParallelScavengeHeap::set_desired_page_size(os::vm_page_size()); - return; - } - - // If using large-page, need to update SpaceAlignment so that spaces are page-size aligned. const size_t min_pages = 4; // 1 for eden + 1 for each survivor + 1 for old const size_t page_sz = os::page_size_for_region_aligned(MinHeapSize, min_pages); - ParallelScavengeHeap::set_desired_page_size(page_sz); - - if (page_sz == os::vm_page_size()) { - log_warning(gc, heap)("MinHeapSize (%zu) must be large enough for 4 * page-size; Disabling UseLargePages for heap", MinHeapSize); - return; - } - // Space is largepage-aligned. - size_t new_alignment = page_sz; + // Can a page size be something else than a power of two? + assert(is_power_of_2((intptr_t)page_sz), "must be a power of 2"); + size_t new_alignment = align_up(page_sz, SpaceAlignment); if (new_alignment != SpaceAlignment) { SpaceAlignment = new_alignment; // Redo everything from the start diff --git a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp index eef9dfbc97c24..18cbe2403d80e 100644 --- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp +++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp @@ -61,18 +61,11 @@ PSYoungGen* ParallelScavengeHeap::_young_gen = nullptr; PSOldGen* ParallelScavengeHeap::_old_gen = nullptr; PSAdaptiveSizePolicy* ParallelScavengeHeap::_size_policy = nullptr; GCPolicyCounters* ParallelScavengeHeap::_gc_policy_counters = nullptr; -size_t ParallelScavengeHeap::_desired_page_size = 0; jint ParallelScavengeHeap::initialize() { const size_t reserved_heap_size = ParallelArguments::heap_reserved_size_bytes(); - assert(_desired_page_size != 0, "Should be initialized"); - ReservedHeapSpace heap_rs = Universe::reserve_heap(reserved_heap_size, HeapAlignment, _desired_page_size); - // Adjust SpaceAlignment based on actually used large page size. - if (UseLargePages) { - SpaceAlignment = MAX2(heap_rs.page_size(), default_space_alignment()); - } - assert(is_aligned(SpaceAlignment, heap_rs.page_size()), "inv"); + ReservedHeapSpace heap_rs = Universe::reserve_heap(reserved_heap_size, HeapAlignment); trace_actual_reserved_page_size(reserved_heap_size, heap_rs); @@ -86,6 +79,7 @@ jint ParallelScavengeHeap::initialize() { card_table->initialize(old_rs.base(), young_rs.base()); CardTableBarrierSet* const barrier_set = new CardTableBarrierSet(card_table); + barrier_set->initialize(); BarrierSet::set_barrier_set(barrier_set); // Set up WorkerThreads diff --git a/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp b/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp index 84732a86880d5..bf777bda29e04 100644 --- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp +++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp @@ -76,9 +76,6 @@ class ParallelScavengeHeap : public CollectedHeap { static PSAdaptiveSizePolicy* _size_policy; static GCPolicyCounters* _gc_policy_counters; - // At startup, calculate the desired OS page-size based on heap size and large-page flags. - static size_t _desired_page_size; - GCMemoryManager* _young_manager; GCMemoryManager* _old_manager; @@ -131,18 +128,6 @@ class ParallelScavengeHeap : public CollectedHeap { _gc_overhead_counter(0), _is_heap_almost_full(false) {} - // The alignment used for spaces in young gen and old gen - constexpr static size_t default_space_alignment() { - constexpr size_t alignment = 64 * K * HeapWordSize; - static_assert(is_power_of_2(alignment), "inv"); - return alignment; - } - - static void set_desired_page_size(size_t page_size) { - assert(is_power_of_2(page_size), "precondition"); - _desired_page_size = page_size; - } - Name kind() const override { return CollectedHeap::Parallel; } diff --git a/src/hotspot/share/gc/parallel/psCompactionManager.hpp b/src/hotspot/share/gc/parallel/psCompactionManager.hpp index 0a404579da832..b013238a9f8cd 100644 --- a/src/hotspot/share/gc/parallel/psCompactionManager.hpp +++ b/src/hotspot/share/gc/parallel/psCompactionManager.hpp @@ -120,6 +120,7 @@ class ParCompactionManager : public CHeapObj { static RegionTaskQueueSet* region_task_queues() { return _region_task_queues; } inline PSMarkTaskQueue* marking_stack() { return &_marking_stack; } + inline void push(PartialArrayState* stat); void push_objArray(oop obj); // To collect per-region live-words in a worker local cache in order to @@ -188,6 +189,7 @@ class ParCompactionManager : public CHeapObj { ParMarkBitMap* mark_bitmap() { return _mark_bitmap; } // Save for later processing. Must not fail. + inline void push(oop obj); inline void push_region(size_t index); // Check mark and maybe push on marking stack. diff --git a/src/hotspot/share/gc/parallel/psCompactionManager.inline.hpp b/src/hotspot/share/gc/parallel/psCompactionManager.inline.hpp index 663cd83be9c75..2c0b8480726ab 100644 --- a/src/hotspot/share/gc/parallel/psCompactionManager.inline.hpp +++ b/src/hotspot/share/gc/parallel/psCompactionManager.inline.hpp @@ -56,6 +56,14 @@ inline bool ParCompactionManager::steal(int queue_num, size_t& region) { return region_task_queues()->steal(queue_num, region); } +inline void ParCompactionManager::push(oop obj) { + marking_stack()->push(ScannerTask(obj)); +} + +inline void ParCompactionManager::push(PartialArrayState* stat) { + marking_stack()->push(ScannerTask(stat)); +} + void ParCompactionManager::push_region(size_t index) { #ifdef ASSERT @@ -70,26 +78,24 @@ void ParCompactionManager::push_region(size_t index) template inline void ParCompactionManager::mark_and_push(T* p) { T heap_oop = RawAccess<>::oop_load(p); - if (CompressedOops::is_null(heap_oop)) { - return; - } - - oop obj = CompressedOops::decode_not_null(heap_oop); - if (!mark_bitmap()->mark_obj(obj)) { - // Marked by another worker. - return; - } - - if (StringDedup::is_enabled() && - java_lang_String::is_instance(obj) && - psStringDedup::is_candidate_from_mark(obj)) { - _string_dedup_requests.add(obj); + if (!CompressedOops::is_null(heap_oop)) { + oop obj = CompressedOops::decode_not_null(heap_oop); + assert(ParallelScavengeHeap::heap()->is_in(obj), "should be in heap"); + + if (mark_bitmap()->mark_obj(obj)) { + if (StringDedup::is_enabled() && + java_lang_String::is_instance(obj) && + psStringDedup::is_candidate_from_mark(obj)) { + _string_dedup_requests.add(obj); + } + + ContinuationGCSupport::transform_stack_chunk(obj); + + assert(_marking_stats_cache != nullptr, "inv"); + _marking_stats_cache->push(obj, obj->size()); + push(obj); + } } - - ContinuationGCSupport::transform_stack_chunk(obj); - - _marking_stats_cache->push(obj, obj->size()); - marking_stack()->push(ScannerTask(obj)); } inline void ParCompactionManager::FollowStackClosure::do_void() { diff --git a/src/hotspot/share/gc/parallel/psOldGen.cpp b/src/hotspot/share/gc/parallel/psOldGen.cpp index 2d4b0698ad0c8..89f22b72b6995 100644 --- a/src/hotspot/share/gc/parallel/psOldGen.cpp +++ b/src/hotspot/share/gc/parallel/psOldGen.cpp @@ -96,7 +96,7 @@ void PSOldGen::initialize_work() { // ObjectSpace stuff // - _object_space = new MutableSpace(virtual_space()->page_size()); + _object_space = new MutableSpace(virtual_space()->alignment()); object_space()->initialize(committed_mr, SpaceDecorator::Clear, SpaceDecorator::Mangle, diff --git a/src/hotspot/share/gc/parallel/psVirtualspace.cpp b/src/hotspot/share/gc/parallel/psVirtualspace.cpp index f4b24fa51af77..3be90b370d186 100644 --- a/src/hotspot/share/gc/parallel/psVirtualspace.cpp +++ b/src/hotspot/share/gc/parallel/psVirtualspace.cpp @@ -29,8 +29,8 @@ #include "utilities/align.hpp" PSVirtualSpace::PSVirtualSpace(ReservedSpace rs, size_t alignment) : - _alignment(alignment), - _page_size(rs.page_size()) { + _alignment(alignment) +{ set_reserved(rs); set_committed(reserved_low_addr(), reserved_low_addr()); DEBUG_ONLY(verify()); @@ -88,8 +88,7 @@ bool PSVirtualSpace::shrink_by(size_t bytes) { #ifndef PRODUCT void PSVirtualSpace::verify() const { - assert(is_aligned(_page_size, os::vm_page_size()), "bad alignment"); - assert(is_aligned(_alignment, _page_size), "inv"); + assert(is_aligned(_alignment, os::vm_page_size()), "bad alignment"); assert(is_aligned(reserved_low_addr(), _alignment), "bad reserved_low_addr"); assert(is_aligned(reserved_high_addr(), _alignment), "bad reserved_high_addr"); assert(is_aligned(committed_low_addr(), _alignment), "bad committed_low_addr"); diff --git a/src/hotspot/share/gc/parallel/psVirtualspace.hpp b/src/hotspot/share/gc/parallel/psVirtualspace.hpp index ca94f4d83b65f..a54a513a11753 100644 --- a/src/hotspot/share/gc/parallel/psVirtualspace.hpp +++ b/src/hotspot/share/gc/parallel/psVirtualspace.hpp @@ -41,9 +41,6 @@ class PSVirtualSpace : public CHeapObj { // ReservedSpace passed to initialize() must be aligned to this value. const size_t _alignment; - // OS page size used. If using Transparent Huge Pages, it's the desired large page-size. - const size_t _page_size; - // Reserved area char* _reserved_low_addr; char* _reserved_high_addr; @@ -71,7 +68,6 @@ class PSVirtualSpace : public CHeapObj { // Accessors (all sizes are bytes). size_t alignment() const { return _alignment; } - size_t page_size() const { return _page_size; } char* reserved_low_addr() const { return _reserved_low_addr; } char* reserved_high_addr() const { return _reserved_high_addr; } char* committed_low_addr() const { return _committed_low_addr; } diff --git a/src/hotspot/share/gc/parallel/psYoungGen.cpp b/src/hotspot/share/gc/parallel/psYoungGen.cpp index b2cce11398d91..c26fdf4740caa 100644 --- a/src/hotspot/share/gc/parallel/psYoungGen.cpp +++ b/src/hotspot/share/gc/parallel/psYoungGen.cpp @@ -83,12 +83,12 @@ void PSYoungGen::initialize_work() { } if (UseNUMA) { - _eden_space = new MutableNUMASpace(virtual_space()->page_size()); + _eden_space = new MutableNUMASpace(virtual_space()->alignment()); } else { - _eden_space = new MutableSpace(virtual_space()->page_size()); + _eden_space = new MutableSpace(virtual_space()->alignment()); } - _from_space = new MutableSpace(virtual_space()->page_size()); - _to_space = new MutableSpace(virtual_space()->page_size()); + _from_space = new MutableSpace(virtual_space()->alignment()); + _to_space = new MutableSpace(virtual_space()->alignment()); // Generation Counters - generation 0, 3 subspaces _gen_counters = new GenerationCounters("new", 0, 3, min_gen_size(), diff --git a/src/hotspot/share/gc/parallel/vmStructs_parallelgc.hpp b/src/hotspot/share/gc/parallel/vmStructs_parallelgc.hpp index f5e7375fca1dd..fa019aa5b4295 100644 --- a/src/hotspot/share/gc/parallel/vmStructs_parallelgc.hpp +++ b/src/hotspot/share/gc/parallel/vmStructs_parallelgc.hpp @@ -40,7 +40,6 @@ /* Parallel GC fields */ \ /**********************/ \ nonstatic_field(PSVirtualSpace, _alignment, const size_t) \ - nonstatic_field(PSVirtualSpace, _page_size, const size_t) \ nonstatic_field(PSVirtualSpace, _reserved_low_addr, char*) \ nonstatic_field(PSVirtualSpace, _reserved_high_addr, char*) \ nonstatic_field(PSVirtualSpace, _committed_low_addr, char*) \ diff --git a/src/hotspot/share/gc/serial/defNewGeneration.cpp b/src/hotspot/share/gc/serial/defNewGeneration.cpp index 413d80bebf4ec..5b7bc7442362e 100644 --- a/src/hotspot/share/gc/serial/defNewGeneration.cpp +++ b/src/hotspot/share/gc/serial/defNewGeneration.cpp @@ -225,12 +225,16 @@ DefNewGeneration::DefNewGeneration(ReservedSpace rs, _promo_failure_drain_in_progress(false), _string_dedup_requests() { + MemRegion cmr((HeapWord*)_virtual_space.low(), + (HeapWord*)_virtual_space.high()); + SerialHeap* gch = SerialHeap::heap(); + + gch->rem_set()->resize_covered_region(cmr); + _eden_space = new ContiguousSpace(); _from_space = new ContiguousSpace(); _to_space = new ContiguousSpace(); - init_spaces(); - // Compute the maximum eden and survivor space sizes. These sizes // are computed assuming the entire reserved space is committed. // These values are exported as performance counters. @@ -252,6 +256,7 @@ DefNewGeneration::DefNewGeneration(ReservedSpace rs, _to_counters = new CSpaceCounters("s1", 2, _max_survivor_size, _to_space, _gen_counters); + compute_space_boundaries(0, SpaceDecorator::Clear, SpaceDecorator::Mangle); update_counters(); _old_gen = nullptr; _tenuring_threshold = MaxTenuringThreshold; @@ -263,51 +268,74 @@ DefNewGeneration::DefNewGeneration(ReservedSpace rs, _gc_tracer = new DefNewTracer(); } -void DefNewGeneration::init_spaces() { - // Using layout: from, to, eden, so only from can be non-empty. - assert(eden()->is_empty(), "precondition"); - assert(to()->is_empty(), "precondition"); - - if (!from()->is_empty()) { - assert((char*) from()->bottom() == _virtual_space.low(), "inv"); - } +void DefNewGeneration::compute_space_boundaries(uintx minimum_eden_size, + bool clear_space, + bool mangle_space) { + // If the spaces are being cleared (only done at heap initialization + // currently), the survivor spaces need not be empty. + // Otherwise, no care is taken for used areas in the survivor spaces + // so check. + assert(clear_space || (to()->is_empty() && from()->is_empty()), + "Initialization of the survivor spaces assumes these are empty"); // Compute sizes - size_t size = _virtual_space.committed_size(); - size_t survivor_size = compute_survivor_size(size, SpaceAlignment); - assert(survivor_size >= from()->used(), "inv"); - assert(size > 2 * survivor_size, "inv"); - size_t eden_size = size - (2 * survivor_size); + uintx size = _virtual_space.committed_size(); + uintx survivor_size = compute_survivor_size(size, SpaceAlignment); + uintx eden_size = size - (2*survivor_size); + if (eden_size > max_eden_size()) { + // Need to reduce eden_size to satisfy the max constraint. The delta needs + // to be 2*SpaceAlignment aligned so that both survivors are properly + // aligned. + uintx eden_delta = align_up(eden_size - max_eden_size(), 2*SpaceAlignment); + eden_size -= eden_delta; + survivor_size += eden_delta/2; + } assert(eden_size > 0 && survivor_size <= eden_size, "just checking"); - // layout: from, to, eden - char* from_start = _virtual_space.low(); - char* to_start = from_start + survivor_size; - char* eden_start = to_start + survivor_size; - char* eden_end = eden_start + eden_size; + if (eden_size < minimum_eden_size) { + // May happen due to 64Kb rounding, if so adjust eden size back up + minimum_eden_size = align_up(minimum_eden_size, SpaceAlignment); + uintx maximum_survivor_size = (size - minimum_eden_size) / 2; + uintx unaligned_survivor_size = + align_down(maximum_survivor_size, SpaceAlignment); + survivor_size = MAX2(unaligned_survivor_size, SpaceAlignment); + eden_size = size - (2*survivor_size); + assert(eden_size > 0 && survivor_size <= eden_size, "just checking"); + assert(eden_size >= minimum_eden_size, "just checking"); + } - assert(eden_end == _virtual_space.high(), "just checking"); + char *eden_start = _virtual_space.low(); + char *from_start = eden_start + eden_size; + char *to_start = from_start + survivor_size; + char *to_end = to_start + survivor_size; + + assert(to_end == _virtual_space.high(), "just checking"); + assert(is_aligned(eden_start, SpaceAlignment), "checking alignment"); assert(is_aligned(from_start, SpaceAlignment), "checking alignment"); assert(is_aligned(to_start, SpaceAlignment), "checking alignment"); - assert(is_aligned(eden_start, SpaceAlignment), "checking alignment"); - assert(is_aligned(eden_end, SpaceAlignment), "checking alignment"); + MemRegion edenMR((HeapWord*)eden_start, (HeapWord*)from_start); MemRegion fromMR((HeapWord*)from_start, (HeapWord*)to_start); - MemRegion toMR ((HeapWord*)to_start, (HeapWord*)eden_start); - MemRegion edenMR((HeapWord*)eden_start, (HeapWord*)eden_end); - - // Reset the spaces for their new regions. - from()->initialize(fromMR, from()->is_empty()); - to()->initialize(toMR, true); - eden()->initialize(edenMR, true); + MemRegion toMR ((HeapWord*)to_start, (HeapWord*)to_end); - post_resize(); -} + // A minimum eden size implies that there is a part of eden that + // is being used and that affects the initialization of any + // newly formed eden. + bool live_in_eden = minimum_eden_size > 0; -void DefNewGeneration::post_resize() { - MemRegion cmr((HeapWord*)_virtual_space.low(), - (HeapWord*)_virtual_space.high()); - SerialHeap::heap()->rem_set()->resize_covered_region(cmr); + // Reset the spaces for their new regions. + eden()->initialize(edenMR, + clear_space && !live_in_eden, + SpaceDecorator::Mangle); + // If clear_space and live_in_eden, we will not have cleared any + // portion of eden above its top. This can cause newly + // expanded space not to be mangled if using ZapUnusedHeapArea. + // We explicitly do such mangling here. + if (ZapUnusedHeapArea && clear_space && live_in_eden && mangle_space) { + eden()->mangle_unused_area(); + } + from()->initialize(fromMR, clear_space, mangle_space); + to()->initialize(toMR, clear_space, mangle_space); } void DefNewGeneration::swap_spaces() { @@ -323,28 +351,20 @@ void DefNewGeneration::swap_spaces() { } bool DefNewGeneration::expand(size_t bytes) { - assert(bytes != 0, "precondition"); - assert(is_aligned(bytes, SpaceAlignment), "precondition"); - + HeapWord* prev_high = (HeapWord*) _virtual_space.high(); bool success = _virtual_space.expand_by(bytes); - if (!success) { - log_info(gc)("Failed to expand young-gen by %zu bytes", bytes); + if (success && ZapUnusedHeapArea) { + // Mangle newly committed space immediately because it + // can be done here more simply that after the new + // spaces have been computed. + HeapWord* new_high = (HeapWord*) _virtual_space.high(); + MemRegion mangle_region(prev_high, new_high); + SpaceMangler::mangle_region(mangle_region); } return success; } -void DefNewGeneration::expand_eden_by(size_t delta_bytes) { - if (!expand(delta_bytes)) { - return; - } - - MemRegion eden_mr{eden()->bottom(), (HeapWord*)_virtual_space.high()}; - eden()->initialize(eden_mr, eden()->is_empty()); - - post_resize(); -} - size_t DefNewGeneration::calculate_thread_increase_size(int threads_count) const { size_t thread_increase_size = 0; // Check an overflow at 'threads_count * NewSizeThreadIncrease'. @@ -377,8 +397,18 @@ size_t DefNewGeneration::adjust_for_thread_increase(size_t new_size_candidate, return desired_new_size; } -size_t DefNewGeneration::calculate_desired_young_gen_bytes() const { - size_t old_size = SerialHeap::heap()->old_gen()->capacity(); +void DefNewGeneration::compute_new_size() { + // This is called after a GC that includes the old generation, so from-space + // will normally be empty. + // Note that we check both spaces, since if scavenge failed they revert roles. + // If not we bail out (otherwise we would have to relocate the objects). + if (!from()->is_empty() || !to()->is_empty()) { + return; + } + + SerialHeap* gch = SerialHeap::heap(); + + size_t old_size = gch->old_gen()->capacity(); size_t new_size_before = _virtual_space.committed_size(); size_t min_new_size = NewSize; size_t max_new_size = reserved().byte_size(); @@ -399,82 +429,46 @@ size_t DefNewGeneration::calculate_desired_young_gen_bytes() const { // Adjust new generation size desired_new_size = clamp(desired_new_size, min_new_size, max_new_size); - if (!from()->is_empty()) { - // Mininum constraint to hold all live objs inside from-space. - size_t min_survivor_size = align_up(from()->used(), alignment); - - // SurvivorRatio := eden_size / survivor_size - // young-gen-size = eden_size + 2 * survivor_size - // = SurvivorRatio * survivor_size + 2 * survivor_size - // = (SurvivorRatio + 2) * survivor_size - size_t min_young_gen_size = min_survivor_size * (SurvivorRatio + 2); - - desired_new_size = MAX2(min_young_gen_size, desired_new_size); - } - assert(is_aligned(desired_new_size, alignment), "postcondition"); - - return desired_new_size; -} - -void DefNewGeneration::resize_inner() { - assert(eden()->is_empty(), "precondition"); - assert(to()->is_empty(), "precondition"); - - size_t current_young_gen_size_bytes = _virtual_space.committed_size(); - size_t desired_young_gen_size_bytes = calculate_desired_young_gen_bytes(); - if (current_young_gen_size_bytes == desired_young_gen_size_bytes) { - return; - } - - // Commit/uncommit - if (desired_young_gen_size_bytes > current_young_gen_size_bytes) { - size_t delta_bytes = desired_young_gen_size_bytes - current_young_gen_size_bytes; - if (!expand(delta_bytes)) { - return; + assert(desired_new_size <= max_new_size, "just checking"); + + bool changed = false; + if (desired_new_size > new_size_before) { + size_t change = desired_new_size - new_size_before; + assert(change % alignment == 0, "just checking"); + if (expand(change)) { + changed = true; } - } else { - size_t delta_bytes = current_young_gen_size_bytes - desired_young_gen_size_bytes; - _virtual_space.shrink_by(delta_bytes); - } - - assert(desired_young_gen_size_bytes == _virtual_space.committed_size(), "inv"); - - init_spaces(); - - log_debug(gc, ergo, heap)("New generation size %zuK->%zuK [eden=%zuK,survivor=%zuK]", - current_young_gen_size_bytes/K, _virtual_space.committed_size()/K, - eden()->capacity()/K, from()->capacity()/K); -} - -void DefNewGeneration::resize_after_young_gc() { - // Called only after successful young-gc. - assert(eden()->is_empty(), "precondition"); - assert(to()->is_empty(), "precondition"); - - if ((char*)to()->bottom() == _virtual_space.low()) { - // layout: to, from, eden; can't resize. - return; - } - - assert((char*)from()->bottom() == _virtual_space.low(), "inv"); - resize_inner(); -} - -void DefNewGeneration::resize_after_full_gc() { - if (eden()->is_empty() && from()->is_empty() && to()->is_empty()) { - resize_inner(); - return; - } - - // Usually the young-gen is empty after full-gc. - // This is the extreme case; expand young-gen to its max size. - if (_virtual_space.uncommitted_size() == 0) { - // Already at its max size. - return; - } - - // Keep from/to and expand eden. - expand_eden_by(_virtual_space.uncommitted_size()); + // If the heap failed to expand to the desired size, + // "changed" will be false. If the expansion failed + // (and at this point it was expected to succeed), + // ignore the failure (leaving "changed" as false). + } + if (desired_new_size < new_size_before && eden()->is_empty()) { + // bail out of shrinking if objects in eden + size_t change = new_size_before - desired_new_size; + assert(change % alignment == 0, "just checking"); + _virtual_space.shrink_by(change); + changed = true; + } + if (changed) { + // The spaces have already been mangled at this point but + // may not have been cleared (set top = bottom) and should be. + // Mangling was done when the heap was being expanded. + compute_space_boundaries(eden()->used(), + SpaceDecorator::Clear, + SpaceDecorator::DontMangle); + MemRegion cmr((HeapWord*)_virtual_space.low(), + (HeapWord*)_virtual_space.high()); + gch->rem_set()->resize_covered_region(cmr); + + log_debug(gc, ergo, heap)( + "New generation size %zuK->%zuK [eden=%zuK,survivor=%zuK]", + new_size_before/K, _virtual_space.committed_size()/K, + eden()->capacity()/K, from()->capacity()/K); + log_trace(gc, ergo, heap)( + " [allowed %zuK extra for %d threads]", + thread_increase_size/K, threads_count); + } } void DefNewGeneration::ref_processor_init() { @@ -489,11 +483,13 @@ size_t DefNewGeneration::capacity() const { + from()->capacity(); // to() is only used during scavenge } + size_t DefNewGeneration::used() const { return eden()->used() + from()->used(); // to() is only used during scavenge } + size_t DefNewGeneration::free() const { return eden()->free() + from()->free(); // to() is only used during scavenge @@ -501,8 +497,7 @@ size_t DefNewGeneration::free() const { size_t DefNewGeneration::max_capacity() const { const size_t reserved_bytes = reserved().byte_size(); - const size_t min_survivor_bytes = SpaceAlignment; - return reserved_bytes - min_survivor_bytes; + return reserved_bytes - compute_survivor_size(reserved_bytes, SpaceAlignment); } bool DefNewGeneration::is_in(const void* p) const { @@ -594,6 +589,7 @@ bool DefNewGeneration::collect(bool clear_all_soft_refs) { IsAliveClosure is_alive(this); age_table()->clear(); + to()->clear(SpaceDecorator::Mangle); YoungGenScanClosure young_gen_cl(this); OldGenScanClosure old_gen_cl(this); @@ -843,18 +839,13 @@ void DefNewGeneration::print_on(outputStream* st) const { to()->print_on(st, "to "); } -HeapWord* DefNewGeneration::expand_and_allocate(size_t word_size) { - assert(SafepointSynchronize::is_at_safepoint(), "precondition"); - assert(Thread::current()->is_VM_thread(), "precondition"); - - size_t eden_free_bytes = eden()->free(); - size_t requested_bytes = word_size * HeapWordSize; - if (eden_free_bytes < requested_bytes) { - size_t expand_bytes = requested_bytes - eden_free_bytes; - expand_eden_by(align_up(expand_bytes, SpaceAlignment)); - } - - HeapWord* result = eden()->allocate(word_size); +HeapWord* DefNewGeneration::allocate(size_t word_size) { + // This is the slow-path allocation for the DefNewGeneration. + // Most allocations are fast-path in compiled code. + // We try to allocate from the eden. If that works, we are happy. + // Note that since DefNewGeneration supports lock-free allocation, we + // have to use it here, as well. + HeapWord* result = eden()->par_allocate(word_size); return result; } diff --git a/src/hotspot/share/gc/serial/defNewGeneration.hpp b/src/hotspot/share/gc/serial/defNewGeneration.hpp index 40d2116cb5847..32b6b32f42fa2 100644 --- a/src/hotspot/share/gc/serial/defNewGeneration.hpp +++ b/src/hotspot/share/gc/serial/defNewGeneration.hpp @@ -131,13 +131,6 @@ class DefNewGeneration: public Generation { return n > alignment ? align_down(n, alignment) : alignment; } - size_t calculate_desired_young_gen_bytes() const; - - void expand_eden_by(size_t delta_bytes); - - void resize_inner(); - void post_resize(); - public: DefNewGeneration(ReservedSpace rs, size_t initial_byte_size, @@ -190,8 +183,9 @@ class DefNewGeneration: public Generation { HeapWord* block_start(const void* p) const; + // Allocate requested size or return null; single-threaded and lock-free versions. + HeapWord* allocate(size_t word_size); HeapWord* par_allocate(size_t word_size); - HeapWord* expand_and_allocate(size_t word_size); void gc_epilogue(); @@ -202,8 +196,8 @@ class DefNewGeneration: public Generation { // Reset for contribution of "to-space". void reset_scratch(); - void resize_after_young_gc(); - void resize_after_full_gc(); + // GC support + void compute_new_size(); bool collect(bool clear_all_soft_refs); @@ -226,9 +220,13 @@ class DefNewGeneration: public Generation { DefNewTracer* gc_tracer() const { return _gc_tracer; } - private: - // Initialize eden/from/to spaces. - void init_spaces(); + protected: + // If clear_space is true, clear the survivor spaces. Eden is + // cleared if the minimum size of eden is 0. If mangle_space + // is true, also mangle the space in debug mode. + void compute_space_boundaries(uintx minimum_eden_size, + bool clear_space, + bool mangle_space); // Return adjusted new size for NewSizeThreadIncrease. // If any overflow happens, revert to previous new size. diff --git a/src/hotspot/share/gc/serial/serialHeap.cpp b/src/hotspot/share/gc/serial/serialHeap.cpp index 8022b317ca64c..3ab88da463387 100644 --- a/src/hotspot/share/gc/serial/serialHeap.cpp +++ b/src/hotspot/share/gc/serial/serialHeap.cpp @@ -182,6 +182,7 @@ jint SerialHeap::initialize() { _rem_set->initialize(young_rs.base(), old_rs.base()); CardTableBarrierSet *bs = new CardTableBarrierSet(_rem_set); + bs->initialize(); BarrierSet::set_barrier_set(bs); _young_gen = new DefNewGeneration(young_rs, NewSize, MinNewSize, MaxNewSize); @@ -268,9 +269,9 @@ size_t SerialHeap::max_capacity() const { } HeapWord* SerialHeap::expand_heap_and_allocate(size_t size, bool is_tlab) { - HeapWord* result = _young_gen->expand_and_allocate(size); + HeapWord* result = _young_gen->allocate(size); - if (result == nullptr && !is_tlab) { + if (result == nullptr) { result = _old_gen->expand_and_allocate(size); } @@ -387,13 +388,14 @@ bool SerialHeap::do_young_collection(bool clear_soft_refs) { // Only update stats for successful young-gc if (result) { _old_gen->update_promote_stats(); - _young_gen->resize_after_young_gc(); } if (should_verify && VerifyAfterGC) { Universe::verify("After GC"); } + _young_gen->compute_new_size(); + print_heap_change(pre_gc_values); // Track memory usage and detect low memory after GC finishes @@ -579,7 +581,7 @@ void SerialHeap::do_full_collection(bool clear_all_soft_refs) { // Adjust generation sizes. _old_gen->compute_new_size(); - _young_gen->resize_after_full_gc(); + _young_gen->compute_new_size(); _old_gen->update_promote_stats(); diff --git a/src/hotspot/share/gc/serial/serialHeap.hpp b/src/hotspot/share/gc/serial/serialHeap.hpp index 3915f8c4af98b..27053b4cc81c5 100644 --- a/src/hotspot/share/gc/serial/serialHeap.hpp +++ b/src/hotspot/share/gc/serial/serialHeap.hpp @@ -55,10 +55,10 @@ class TenuredGeneration; // +-- generation boundary (fixed after startup) // | // |<- young gen (reserved MaxNewSize) ->|<- old gen (reserved MaxOldSize) ->| -// +--------+--------+-----------------+--------+---------------+-------------------+ -// | from | to | eden | | old | | -// | (to) | (from) | | | | | -// +--------+--------+-----------------+--------+---------------+-------------------+ +// +-----------------+--------+--------+--------+---------------+-------------------+ +// | eden | from | to | | old | | +// | | (to) | (from) | | | | +// +-----------------+--------+--------+--------+---------------+-------------------+ // |<- committed ->| |<- committed ->| // class SerialHeap : public CollectedHeap { diff --git a/src/hotspot/share/gc/serial/tenuredGeneration.cpp b/src/hotspot/share/gc/serial/tenuredGeneration.cpp index f68847ed1a6b9..a28a8c8e1cb92 100644 --- a/src/hotspot/share/gc/serial/tenuredGeneration.cpp +++ b/src/hotspot/share/gc/serial/tenuredGeneration.cpp @@ -314,7 +314,7 @@ TenuredGeneration::TenuredGeneration(ReservedSpace rs, HeapWord* bottom = (HeapWord*) _virtual_space.low(); HeapWord* end = (HeapWord*) _virtual_space.high(); _the_space = new ContiguousSpace(); - _the_space->initialize(MemRegion(bottom, end), SpaceDecorator::Clear); + _the_space->initialize(MemRegion(bottom, end), SpaceDecorator::Clear, SpaceDecorator::Mangle); // If we don't shrink the heap in steps, '_shrink_factor' is always 100%. _shrink_factor = ShrinkHeapInSteps ? 0 : 100; _capacity_at_prologue = 0; diff --git a/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp b/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp index c4eefee5f6571..e12e7b56e2328 100644 --- a/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp +++ b/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp @@ -115,7 +115,7 @@ uint8_t BarrierStubC2::barrier_data() const { void BarrierStubC2::preserve(Register r) { const VMReg vm_reg = r->as_VMReg(); assert(vm_reg->is_Register(), "r must be a general-purpose register"); - _preserve.insert(OptoReg::as_OptoReg(vm_reg)); + _preserve.Insert(OptoReg::as_OptoReg(vm_reg)); } void BarrierStubC2::dont_preserve(Register r) { @@ -124,7 +124,7 @@ void BarrierStubC2::dont_preserve(Register r) { // Subtract the given register and all its sub-registers (e.g. {R11, R11_H} // for r11 in aarch64). do { - _preserve.remove(OptoReg::as_OptoReg(vm_reg)); + _preserve.Remove(OptoReg::as_OptoReg(vm_reg)); vm_reg = vm_reg->next(); } while (vm_reg->is_Register() && !vm_reg->is_concrete()); } @@ -1171,7 +1171,7 @@ void BarrierSetC2::compute_liveness_at_stubs() const { // Initialize to union of successors for (uint i = 0; i < block->_num_succs; i++) { const uint succ_id = block->_succs[i]->_pre_order; - new_live.or_with(live[succ_id]); + new_live.OR(live[succ_id]); } // Walk block backwards, computing liveness @@ -1182,7 +1182,7 @@ void BarrierSetC2::compute_liveness_at_stubs() const { if (!bs_state->needs_livein_data()) { RegMask* const regs = bs_state->live(node); if (regs != nullptr) { - regs->or_with(new_live); + regs->OR(new_live); } } @@ -1190,10 +1190,10 @@ void BarrierSetC2::compute_liveness_at_stubs() const { const OptoReg::Name first = bs->refine_register(node, regalloc->get_reg_first(node)); const OptoReg::Name second = bs->refine_register(node, regalloc->get_reg_second(node)); if (first != OptoReg::Bad) { - new_live.remove(first); + new_live.Remove(first); } if (second != OptoReg::Bad) { - new_live.remove(second); + new_live.Remove(second); } // Add use bits @@ -1202,10 +1202,10 @@ void BarrierSetC2::compute_liveness_at_stubs() const { const OptoReg::Name first = bs->refine_register(use, regalloc->get_reg_first(use)); const OptoReg::Name second = bs->refine_register(use, regalloc->get_reg_second(use)); if (first != OptoReg::Bad) { - new_live.insert(first); + new_live.Insert(first); } if (second != OptoReg::Bad) { - new_live.insert(second); + new_live.Insert(second); } } @@ -1213,16 +1213,16 @@ void BarrierSetC2::compute_liveness_at_stubs() const { if (bs_state->needs_livein_data()) { RegMask* const regs = bs_state->live(node); if (regs != nullptr) { - regs->or_with(new_live); + regs->OR(new_live); } } } // Now at block top, see if we have any changes - new_live.subtract(old_live); - if (!new_live.is_empty()) { + new_live.SUBTRACT(old_live); + if (!new_live.is_Empty()) { // Liveness has refined, update and propagate to prior blocks - old_live.or_with(new_live); + old_live.OR(new_live); for (uint i = 1; i < block->num_preds(); ++i) { Block* const pred = cfg->get_block_for_node(block->pred(i)); worklist.push(pred); diff --git a/src/hotspot/share/gc/shared/cardTableBarrierSet.cpp b/src/hotspot/share/gc/shared/cardTableBarrierSet.cpp index de514f64be2b0..dfa00636dec5c 100644 --- a/src/hotspot/share/gc/shared/cardTableBarrierSet.cpp +++ b/src/hotspot/share/gc/shared/cardTableBarrierSet.cpp @@ -57,6 +57,7 @@ CardTableBarrierSet::CardTableBarrierSet(BarrierSetAssembler* barrier_set_assemb barrier_set_c1, barrier_set_c2, fake_rtti.add_tag(BarrierSet::CardTableBarrierSet)), + _defer_initial_card_mark(false), _card_table(card_table) {} @@ -65,9 +66,14 @@ CardTableBarrierSet::CardTableBarrierSet(CardTable* card_table) : make_barrier_set_c1(), make_barrier_set_c2(), BarrierSet::FakeRtti(BarrierSet::CardTableBarrierSet)), + _defer_initial_card_mark(false), _card_table(card_table) {} +void CardTableBarrierSet::initialize() { + initialize_deferred_card_mark_barriers(); +} + CardTableBarrierSet::~CardTableBarrierSet() { delete _card_table; } @@ -102,7 +108,9 @@ void CardTableBarrierSet::print_on(outputStream* st) const { // to the post-barrier, we note that G1 needs a RS update barrier // which simply enqueues a (sequence of) dirty cards which may // optionally be refined by the concurrent update threads. Note -// that this barrier need only be applied to a non-young write. +// that this barrier need only be applied to a non-young write, +// but, because of the presence of concurrent refinement, +// must strictly follow the oop-store. // // For any future collector, this code should be reexamined with // that specific collector in mind, and the documentation above suitably @@ -112,13 +120,72 @@ void CardTableBarrierSet::on_slowpath_allocation_exit(JavaThread* thread, oop ne if (!ReduceInitialCardMarks) { return; } + // If a previous card-mark was deferred, flush it now. + flush_deferred_card_mark_barrier(thread); if (new_obj->is_typeArray() || _card_table->is_in_young(new_obj)) { // Arrays of non-references don't need a post-barrier. + // The deferred_card_mark region should be empty + // following the flush above. + assert(thread->deferred_card_mark().is_empty(), "Error"); } else { MemRegion mr(cast_from_oop(new_obj), new_obj->size()); assert(!mr.is_empty(), "Error"); - // Do the card mark - write_region(mr); + if (_defer_initial_card_mark) { + // Defer the card mark + thread->set_deferred_card_mark(mr); + } else { + // Do the card mark + write_region(mr); + } } #endif // COMPILER2_OR_JVMCI } + +void CardTableBarrierSet::initialize_deferred_card_mark_barriers() { + // Used for ReduceInitialCardMarks (when COMPILER2 or JVMCI is used); + // otherwise remains unused. +#if COMPILER2_OR_JVMCI + _defer_initial_card_mark = CompilerConfig::is_c2_or_jvmci_compiler_enabled() && ReduceInitialCardMarks + && (DeferInitialCardMark || card_mark_must_follow_store()); +#else + assert(_defer_initial_card_mark == false, "Who would set it?"); +#endif +} + +void CardTableBarrierSet::flush_deferred_card_mark_barrier(JavaThread* thread) { +#if COMPILER2_OR_JVMCI + MemRegion deferred = thread->deferred_card_mark(); + if (!deferred.is_empty()) { + assert(_defer_initial_card_mark, "Otherwise should be empty"); + { + // Verify that the storage points to a parsable object in heap + DEBUG_ONLY(oop old_obj = cast_to_oop(deferred.start());) + assert(!_card_table->is_in_young(old_obj), + "Else should have been filtered in on_slowpath_allocation_exit()"); + assert(oopDesc::is_oop(old_obj), "Not an oop"); + assert(deferred.word_size() == old_obj->size(), + "Mismatch: multiple objects?"); + } + write_region(thread, deferred); + // "Clear" the deferred_card_mark field + thread->set_deferred_card_mark(MemRegion()); + } + assert(thread->deferred_card_mark().is_empty(), "invariant"); +#else + assert(!_defer_initial_card_mark, "Should be false"); + assert(thread->deferred_card_mark().is_empty(), "Should be empty"); +#endif +} + +void CardTableBarrierSet::on_thread_detach(Thread* thread) { + // The deferred store barriers must all have been flushed to the + // card-table (or other remembered set structure) before GC starts + // processing the card-table (or other remembered set). + if (thread->is_Java_thread()) { // Only relevant for Java threads. + flush_deferred_card_mark_barrier(JavaThread::cast(thread)); + } +} + +bool CardTableBarrierSet::card_mark_must_follow_store() const { + return false; +} diff --git a/src/hotspot/share/gc/shared/cardTableBarrierSet.hpp b/src/hotspot/share/gc/shared/cardTableBarrierSet.hpp index a5646c303f38a..13f3e0783a668 100644 --- a/src/hotspot/share/gc/shared/cardTableBarrierSet.hpp +++ b/src/hotspot/share/gc/shared/cardTableBarrierSet.hpp @@ -47,6 +47,9 @@ class CardTableBarrierSet: public ModRefBarrierSet { protected: typedef CardTable::CardValue CardValue; + // Used in support of ReduceInitialCardMarks; only consulted if COMPILER2 + // or INCLUDE_JVMCI is being used + bool _defer_initial_card_mark; CardTable* _card_table; CardTableBarrierSet(BarrierSetAssembler* barrier_set_assembler, @@ -61,6 +64,13 @@ class CardTableBarrierSet: public ModRefBarrierSet { CardTable* card_table() const { return _card_table; } + void initialize(); + + void write_region(JavaThread* thread, MemRegion mr) { + write_region(mr); + } + + public: // Record a reference update. Note that these versions are precise! // The scanning code has to handle the fact that the write barrier may be // either precise or imprecise. We make non-virtual inline variants of @@ -70,7 +80,29 @@ class CardTableBarrierSet: public ModRefBarrierSet { virtual void write_region(MemRegion mr); + // ReduceInitialCardMarks + void initialize_deferred_card_mark_barriers(); + + // If the CollectedHeap was asked to defer a store barrier above, + // this informs it to flush such a deferred store barrier to the + // remembered set. + void flush_deferred_card_mark_barrier(JavaThread* thread); + + // If a compiler is eliding store barriers for TLAB-allocated objects, + // we will be informed of a slow-path allocation by a call + // to on_slowpath_allocation_exit() below. Such a call precedes the + // initialization of the object itself, and no post-store-barriers will + // be issued. Some heap types require that the barrier strictly follows + // the initializing stores. (This is currently implemented by deferring the + // barrier until the next slow-path allocation or gc-related safepoint.) + // This interface answers whether a particular barrier type needs the card + // mark to be thus strictly sequenced after the stores. + virtual bool card_mark_must_follow_store() const; + virtual void on_slowpath_allocation_exit(JavaThread* thread, oop new_obj); + virtual void on_thread_detach(Thread* thread); + + virtual void make_parsable(JavaThread* thread) { flush_deferred_card_mark_barrier(thread); } virtual void print_on(outputStream* st) const; diff --git a/src/hotspot/share/gc/shared/collectedHeap.cpp b/src/hotspot/share/gc/shared/collectedHeap.cpp index ea20b8ce4b2ac..8ef73c6a0b825 100644 --- a/src/hotspot/share/gc/shared/collectedHeap.cpp +++ b/src/hotspot/share/gc/shared/collectedHeap.cpp @@ -623,8 +623,6 @@ void CollectedHeap::stall_for_vm_shutdown() { // - short enough to avoid excessive stall time if the shutdown itself // triggers a GC. JavaThread::current()->sleep(2 * MILLIUNITS); - - ResourceMark rm; log_warning(gc, alloc)("%s: Stall for VM-Shutdown timed out; allocation may fail with OOME", Thread::current()->name()); } diff --git a/src/hotspot/share/gc/shared/gc_globals.hpp b/src/hotspot/share/gc/shared/gc_globals.hpp index 956bffde15625..0b245026d68aa 100644 --- a/src/hotspot/share/gc/shared/gc_globals.hpp +++ b/src/hotspot/share/gc/shared/gc_globals.hpp @@ -418,6 +418,10 @@ "dictionary, classloader_data_graph, metaspace, jni_handles, " \ "codecache_oops, resolved_method_table, stringdedup") \ \ + product(bool, DeferInitialCardMark, false, DIAGNOSTIC, \ + "When +ReduceInitialCardMarks, explicitly defer any that " \ + "may arise from new_pre_store_barrier") \ + \ product(bool, UseCondCardMark, false, \ "Check for already marked card before updating card table") \ \ diff --git a/src/hotspot/share/gc/shared/modRefBarrierSet.hpp b/src/hotspot/share/gc/shared/modRefBarrierSet.hpp index c078d151233d1..15ac797111835 100644 --- a/src/hotspot/share/gc/shared/modRefBarrierSet.hpp +++ b/src/hotspot/share/gc/shared/modRefBarrierSet.hpp @@ -53,6 +53,8 @@ class ModRefBarrierSet: public BarrierSet { // Causes all refs in "mr" to be assumed to be modified (by this JavaThread). virtual void write_region(MemRegion mr) = 0; + // Causes all refs in "mr" to be assumed to be modified by the given JavaThread. + virtual void write_region(JavaThread* thread, MemRegion mr) = 0; // Operations on arrays, or general regions (e.g., for "clone") may be // optimized by some barriers. diff --git a/src/hotspot/share/gc/shared/space.cpp b/src/hotspot/share/gc/shared/space.cpp index 011a0f5cfd83c..08476cb2a3ad6 100644 --- a/src/hotspot/share/gc/shared/space.cpp +++ b/src/hotspot/share/gc/shared/space.cpp @@ -44,7 +44,8 @@ ContiguousSpace::ContiguousSpace(): _top(nullptr) {} void ContiguousSpace::initialize(MemRegion mr, - bool clear_space) { + bool clear_space, + bool mangle_space) { HeapWord* bottom = mr.start(); HeapWord* end = mr.end(); assert(Universe::on_page_boundary(bottom) && Universe::on_page_boundary(end), @@ -52,10 +53,7 @@ void ContiguousSpace::initialize(MemRegion mr, set_bottom(bottom); set_end(end); if (clear_space) { - clear(SpaceDecorator::DontMangle); - } - if (ZapUnusedHeapArea) { - mangle_unused_area(); + clear(mangle_space); } } diff --git a/src/hotspot/share/gc/shared/space.hpp b/src/hotspot/share/gc/shared/space.hpp index 7f2887275b3c8..75dd3f998d63e 100644 --- a/src/hotspot/share/gc/shared/space.hpp +++ b/src/hotspot/share/gc/shared/space.hpp @@ -101,7 +101,7 @@ class ContiguousSpace: public CHeapObj { // any purpose. The "mr" arguments gives the bounds of the space, and // the "clear_space" argument should be true unless the memory in "mr" is // known to be zeroed. - void initialize(MemRegion mr, bool clear_space); + void initialize(MemRegion mr, bool clear_space, bool mangle_space); // The "clear" method must be called on a region that may have // had allocation performed in it, but is now to be considered empty. diff --git a/src/hotspot/share/gc/shared/vmStructs_gc.hpp b/src/hotspot/share/gc/shared/vmStructs_gc.hpp index 9d84a56fbd748..bba9c9e099fc9 100644 --- a/src/hotspot/share/gc/shared/vmStructs_gc.hpp +++ b/src/hotspot/share/gc/shared/vmStructs_gc.hpp @@ -88,6 +88,7 @@ nonstatic_field(CardTable, _byte_map_size, const size_t) \ nonstatic_field(CardTable, _byte_map, CardTable::CardValue*) \ nonstatic_field(CardTable, _byte_map_base, CardTable::CardValue*) \ + nonstatic_field(CardTableBarrierSet, _defer_initial_card_mark, bool) \ nonstatic_field(CardTableBarrierSet, _card_table, CardTable*) \ \ static_field(CollectedHeap, _lab_alignment_reserve, size_t) \ diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.hpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.hpp index 66bfc3375a311..014a4d9913119 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.hpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.hpp @@ -32,62 +32,25 @@ #include "memory/allocation.hpp" #include "utilities/numberSeq.hpp" -/** - * ShenanoahAllocationRate maintains a truncated history of recently sampled allocation rates for the purpose of providing - * informed estimates of current and future allocation rates based on weighted averages and standard deviations of the - * truncated history. More recently sampled allocations are weighted more heavily than older samples when computing - * averages and standard deviations. - */ class ShenandoahAllocationRate : public CHeapObj { public: explicit ShenandoahAllocationRate(); - - // Reset the _last_sample_value to zero, _last_sample_time to current time. void allocation_counter_reset(); - // Force an allocation rate sample to be taken, even if the time since last sample is not greater than - // 1s/ShenandoahAdaptiveSampleFrequencyHz, except when current_time - _last_sample_time < MinSampleTime (2 ms). - // The sampled allocation rate is computed from (allocated - _last_sample_value) / (current_time - _last_sample_time). - // Return the newly computed rate if the sample is taken, zero if it is not an appropriate time to add a sample. - // In the case that a new sample is not taken, overwrite unaccounted_bytes_allocated with bytes allocated since - // the previous sample was taken (allocated - _last_sample_value). Otherwise, overwrite unaccounted_bytes_allocated - // with 0. double force_sample(size_t allocated, size_t &unaccounted_bytes_allocated); - - // Add an allocation rate sample if the time since last sample is greater than 1s/ShenandoahAdaptiveSampleFrequencyHz. - // The sampled allocation rate is computed from (allocated - _last_sample_value) / (current_time - _last_sample_time). - // Return the newly computed rate if the sample is taken, zero if it is not an appropriate time to add a sample. double sample(size_t allocated); - // Return an estimate of the upper bound on allocation rate, with the upper bound computed as the weighted average - // of recently sampled instantaneous allocation rates added to sds times the standard deviation computed for the - // sequence of recently sampled average allocation rates. double upper_bound(double sds) const; - - // Test whether rate significantly diverges from the computed average allocation rate. If so, return true. - // Otherwise, return false. Significant divergence is recognized if (rate - _rate.avg()) / _rate.sd() > threshold. bool is_spiking(double rate, double threshold) const; private: - // Return the instantaneous rate calculated from (allocated - _last_sample_value) / (time - _last_sample_time). - // Return Sentinel value 0.0 if (time - _last_sample_time) == 0 or if (allocated <= _last_sample_value). double instantaneous_rate(double time, size_t allocated) const; - // Time at which previous allocation rate sample was collected. double _last_sample_time; - - // Bytes allocated as of the time at which previous allocation rate sample was collected. size_t _last_sample_value; - - // The desired interval of time between consecutive samples of the allocation rate. double _interval_sec; - - // Holds a sequence of the most recently sampled instantaneous allocation rates TruncatedSeq _rate; - - // Holds a sequence of the most recently computed weighted average of allocation rates, with each weighted average - // computed immediately after an instantaneous rate was sampled TruncatedSeq _rate_avg; }; @@ -191,8 +154,6 @@ class ShenandoahAdaptiveHeuristics : public ShenandoahHeuristics { } public: - // Sample the allocation rate at GC trigger time if possible. Return the number of allocated bytes that were - // not accounted for in the sample. This must be called before resetting bytes allocated since gc start. virtual size_t force_alloc_rate_sample(size_t bytes_allocated) override { size_t unaccounted_bytes; _allocation_rate.force_sample(bytes_allocated, unaccounted_bytes); diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp index a2cccec842373..c7067b2e5abf7 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp @@ -127,7 +127,7 @@ void ShenandoahGenerationalHeuristics::choose_collection_set(ShenandoahCollectio // Reclaim humongous regions here, and count them as the immediate garbage #ifdef ASSERT bool reg_live = region->has_live(); - bool bm_live = _generation->complete_marking_context()->is_marked(cast_to_oop(region->bottom())); + bool bm_live = heap->active_generation()->complete_marking_context()->is_marked(cast_to_oop(region->bottom())); assert(reg_live == bm_live, "Humongous liveness and marks should agree. Region live: %s; Bitmap live: %s; Region Live Words: %zu", BOOL_TO_STR(reg_live), BOOL_TO_STR(bm_live), region->get_live_data_words()); diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp index 478c569618876..c8a0c3dc51837 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahHeuristics.cpp @@ -73,10 +73,9 @@ ShenandoahHeuristics::~ShenandoahHeuristics() { } void ShenandoahHeuristics::choose_collection_set(ShenandoahCollectionSet* collection_set) { - ShenandoahHeap* heap = ShenandoahHeap::heap(); - assert(collection_set->is_empty(), "Must be empty"); - assert(!heap->mode()->is_generational(), "Wrong heuristic for heap mode"); + + ShenandoahHeap* heap = ShenandoahHeap::heap(); // Check all pinned regions have updated status before choosing the collection set. heap->assert_pinned_region_status(); @@ -121,7 +120,7 @@ void ShenandoahHeuristics::choose_collection_set(ShenandoahCollectionSet* collec // Reclaim humongous regions here, and count them as the immediate garbage #ifdef ASSERT bool reg_live = region->has_live(); - bool bm_live = heap->global_generation()->complete_marking_context()->is_marked(cast_to_oop(region->bottom())); + bool bm_live = heap->gc_generation()->complete_marking_context()->is_marked(cast_to_oop(region->bottom())); assert(reg_live == bm_live, "Humongous liveness and marks should agree. Region live: %s; Bitmap live: %s; Region Live Words: %zu", BOOL_TO_STR(reg_live), BOOL_TO_STR(bm_live), region->get_live_data_words()); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp b/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp index baeaffb9c7ba1..3d9fa10b0fc6e 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahAsserts.cpp @@ -425,16 +425,6 @@ void ShenandoahAsserts::assert_marked_strong(void *interior_loc, oop obj, const } } -void ShenandoahAsserts::assert_mark_complete(HeapWord* obj, const char* file, int line) { - const ShenandoahHeap* heap = ShenandoahHeap::heap(); - const ShenandoahHeapRegion* region = heap->heap_region_containing(obj); - const ShenandoahGeneration* generation = heap->generation_for(region->affiliation()); - if (!generation->is_mark_complete()) { - ShenandoahMessageBuffer msg("Marking should be complete for object " PTR_FORMAT " in the %s generation", p2i(obj), generation->name()); - report_vm_error(file, line, msg.buffer()); - } -} - void ShenandoahAsserts::assert_in_cset(void* interior_loc, oop obj, const char* file, int line) { assert_correct(interior_loc, obj, file, line); @@ -552,6 +542,23 @@ void ShenandoahAsserts::assert_control_or_vm_thread_at_safepoint(bool at_safepoi report_vm_error(file, line, msg.buffer()); } +void ShenandoahAsserts::assert_generations_reconciled(const char* file, int line) { + if (!ShenandoahSafepoint::is_at_shenandoah_safepoint()) { + // Only shenandoah safepoint operations participate in the active/gc generation scheme + return; + } + + ShenandoahHeap* heap = ShenandoahHeap::heap(); + ShenandoahGeneration* ggen = heap->gc_generation(); + ShenandoahGeneration* agen = heap->active_generation(); + if (agen == ggen) { + return; + } + + ShenandoahMessageBuffer msg("Active(%s) & GC(%s) Generations aren't reconciled", agen->name(), ggen->name()); + report_vm_error(file, line, msg.buffer()); +} + bool ShenandoahAsserts::extract_klass_safely(oop obj, narrowKlass& nk, const Klass*& k) { nk = 0; k = nullptr; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahAsserts.hpp b/src/hotspot/share/gc/shenandoah/shenandoahAsserts.hpp index d0fc3e213c8e3..e31ef7c99aae3 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahAsserts.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahAsserts.hpp @@ -65,9 +65,6 @@ class ShenandoahAsserts { static void assert_marked(void* interior_loc, oop obj, const char* file, int line); static void assert_marked_weak(void* interior_loc, oop obj, const char* file, int line); static void assert_marked_strong(void* interior_loc, oop obj, const char* file, int line); - - // Assert that marking is complete for the generation where this obj resides - static void assert_mark_complete(HeapWord* obj, const char* file, int line); static void assert_in_cset(void* interior_loc, oop obj, const char* file, int line); static void assert_not_in_cset(void* interior_loc, oop obj, const char* file, int line); static void assert_not_in_cset_loc(void* interior_loc, const char* file, int line); @@ -79,6 +76,7 @@ class ShenandoahAsserts { static void assert_heaplocked_or_safepoint(const char* file, int line); static void assert_control_or_vm_thread_at_safepoint(bool at_safepoint, const char* file, int line); static void assert_generational(const char* file, int line); + static void assert_generations_reconciled(const char* file, int line); // Given a possibly invalid oop, extract narrowKlass (if UCCP) and Klass* // from it safely. @@ -135,9 +133,6 @@ class ShenandoahAsserts { #define shenandoah_assert_marked_strong(interior_loc, obj) \ ShenandoahAsserts::assert_marked_strong(interior_loc, obj, __FILE__, __LINE__) -#define shenandoah_assert_mark_complete(obj) \ - ShenandoahAsserts::assert_mark_complete(obj, __FILE__, __LINE__) - #define shenandoah_assert_in_cset_if(interior_loc, obj, condition) \ if (condition) ShenandoahAsserts::assert_in_cset(interior_loc, obj, __FILE__, __LINE__) #define shenandoah_assert_in_cset_except(interior_loc, obj, exception) \ @@ -189,6 +184,10 @@ class ShenandoahAsserts { #define shenandoah_assert_generational() \ ShenandoahAsserts::assert_generational(__FILE__, __LINE__) +// Some limited sanity checking of the _gc_generation and _active_generation fields of ShenandoahHeap +#define shenandoah_assert_generations_reconciled() \ + ShenandoahAsserts::assert_generations_reconciled(__FILE__, __LINE__) + #else #define shenandoah_assert_in_heap_bounds(interior_loc, obj) #define shenandoah_assert_in_heap_bounds_or_null(interior_loc, obj) @@ -218,8 +217,6 @@ class ShenandoahAsserts { #define shenandoah_assert_marked_strong_except(interior_loc, obj, exception) #define shenandoah_assert_marked_strong(interior_loc, obj) -#define shenandoah_assert_mark_complete(obj) - #define shenandoah_assert_in_cset_if(interior_loc, obj, condition) #define shenandoah_assert_in_cset_except(interior_loc, obj, exception) #define shenandoah_assert_in_cset(interior_loc, obj) @@ -244,6 +241,7 @@ class ShenandoahAsserts { #define shenandoah_assert_control_or_vm_thread() #define shenandoah_assert_control_or_vm_thread_at_safepoint() #define shenandoah_assert_generational() +#define shenandoah_assert_generations_reconciled() #endif diff --git a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp index 2aa37d7c575ab..5d19a6a34e31e 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp @@ -89,20 +89,10 @@ bool ShenandoahBarrierSet::need_keep_alive_barrier(DecoratorSet decorators, Basi void ShenandoahBarrierSet::on_slowpath_allocation_exit(JavaThread* thread, oop new_obj) { #if COMPILER2_OR_JVMCI - if (ReduceInitialCardMarks && ShenandoahCardBarrier && !ShenandoahHeap::heap()->is_in_young(new_obj)) { - log_debug(gc)("Newly allocated object (" PTR_FORMAT ") is not in the young generation", p2i(new_obj)); - // This can happen when an object is newly allocated, but we come to a safepoint before returning - // the object. If the safepoint runs a degenerated cycle that is upgraded to a full GC, this object - // will have survived two GC cycles. If the tenuring age is very low (1), this object may be promoted. - // In this case, we have an allocated object, but it has received no stores yet. If card marking barriers - // have been elided, we could end up with an object in old holding pointers to young that won't be in - // the remembered set. The solution here is conservative, but this problem should be rare, and it will - // correct itself on subsequent cycles when the remembered set is updated. - ShenandoahGenerationalHeap::heap()->old_generation()->card_scan()->mark_range_as_dirty( - cast_from_oop(new_obj), new_obj->size() - ); - } + assert(!ReduceInitialCardMarks || !ShenandoahCardBarrier || ShenandoahGenerationalHeap::heap()->is_in_young(new_obj), + "Allocating new object outside of young generation: " INTPTR_FORMAT, p2i(new_obj)); #endif // COMPILER2_OR_JVMCI + assert(thread->deferred_card_mark().is_empty(), "We don't use this"); } void ShenandoahBarrierSet::on_thread_create(Thread* thread) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp index 9613422496af6..456b9fe6d3c85 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp @@ -91,8 +91,8 @@ class ShenandoahBreakpointMarkScope : public StackObj { }; ShenandoahConcurrentGC::ShenandoahConcurrentGC(ShenandoahGeneration* generation, bool do_old_gc_bootstrap) : - ShenandoahGC(generation), _mark(generation), + _generation(generation), _degen_point(ShenandoahDegenPoint::_degenerated_unset), _abbreviated(false), _do_old_gc_bootstrap(do_old_gc_bootstrap) { @@ -576,7 +576,7 @@ void ShenandoahConcurrentGC::entry_promote_in_place() const { ShenandoahGCWorkerPhase worker_phase(ShenandoahPhaseTimings::promote_in_place); EventMark em("%s", "Promote in place"); - ShenandoahGenerationalHeap::heap()->promote_regions_in_place(_generation, true); + ShenandoahGenerationalHeap::heap()->promote_regions_in_place(true); } void ShenandoahConcurrentGC::entry_update_thread_roots() { @@ -706,7 +706,7 @@ void ShenandoahConcurrentGC::op_init_mark() { if (ShenandoahVerify) { ShenandoahTimingsTracker v(ShenandoahPhaseTimings::init_mark_verify); - heap->verifier()->verify_before_concmark(_generation); + heap->verifier()->verify_before_concmark(); } if (VerifyBeforeGC) { @@ -763,7 +763,7 @@ void ShenandoahConcurrentGC::op_final_mark() { assert(!heap->has_forwarded_objects(), "No forwarded objects on this path"); if (ShenandoahVerify) { - heap->verifier()->verify_roots_no_forwarded(_generation); + heap->verifier()->verify_roots_no_forwarded(); } if (!heap->cancelled_gc()) { @@ -791,7 +791,7 @@ void ShenandoahConcurrentGC::op_final_mark() { if (ShenandoahVerify) { ShenandoahTimingsTracker v(ShenandoahPhaseTimings::final_mark_verify); - heap->verifier()->verify_before_evacuation(_generation); + heap->verifier()->verify_before_evacuation(); } heap->set_evacuation_in_progress(true); @@ -806,9 +806,9 @@ void ShenandoahConcurrentGC::op_final_mark() { if (ShenandoahVerify) { ShenandoahTimingsTracker v(ShenandoahPhaseTimings::final_mark_verify); if (has_in_place_promotions(heap)) { - heap->verifier()->verify_after_concmark_with_promotions(_generation); + heap->verifier()->verify_after_concmark_with_promotions(); } else { - heap->verifier()->verify_after_concmark(_generation); + heap->verifier()->verify_after_concmark(); } } } @@ -877,20 +877,18 @@ void ShenandoahConcurrentGC::op_weak_refs() { class ShenandoahEvacUpdateCleanupOopStorageRootsClosure : public BasicOopIterateClosure { private: ShenandoahHeap* const _heap; - ShenandoahGeneration* const _generation; ShenandoahMarkingContext* const _mark_context; bool _evac_in_progress; Thread* const _thread; public: - explicit ShenandoahEvacUpdateCleanupOopStorageRootsClosure(ShenandoahGeneration* generation); + ShenandoahEvacUpdateCleanupOopStorageRootsClosure(); void do_oop(oop* p); void do_oop(narrowOop* p); }; -ShenandoahEvacUpdateCleanupOopStorageRootsClosure::ShenandoahEvacUpdateCleanupOopStorageRootsClosure(ShenandoahGeneration* generation) : +ShenandoahEvacUpdateCleanupOopStorageRootsClosure::ShenandoahEvacUpdateCleanupOopStorageRootsClosure() : _heap(ShenandoahHeap::heap()), - _generation(generation), _mark_context(ShenandoahHeap::heap()->marking_context()), _evac_in_progress(ShenandoahHeap::heap()->is_evacuation_in_progress()), _thread(Thread::current()) { @@ -900,7 +898,8 @@ void ShenandoahEvacUpdateCleanupOopStorageRootsClosure::do_oop(oop* p) { const oop obj = RawAccess<>::oop_load(p); if (!CompressedOops::is_null(obj)) { if (!_mark_context->is_marked(obj)) { - if (_generation->contains(obj)) { + shenandoah_assert_generations_reconciled(); + if (_heap->is_in_active_generation(obj)) { // Note: The obj is dead here. Do not touch it, just clear. ShenandoahHeap::atomic_clear_oop(p, obj); } @@ -943,16 +942,14 @@ class ShenandoahConcurrentWeakRootsEvacUpdateTask : public WorkerTask { ShenandoahClassLoaderDataRoots _cld_roots; ShenandoahConcurrentNMethodIterator _nmethod_itr; - ShenandoahGeneration* _generation; ShenandoahPhaseTimings::Phase _phase; public: - ShenandoahConcurrentWeakRootsEvacUpdateTask(ShenandoahGeneration* generation, ShenandoahPhaseTimings::Phase phase) : + ShenandoahConcurrentWeakRootsEvacUpdateTask(ShenandoahPhaseTimings::Phase phase) : WorkerTask("Shenandoah Evacuate/Update Concurrent Weak Roots"), _vm_roots(phase), _cld_roots(phase, ShenandoahHeap::heap()->workers()->active_workers(), false /*heap iteration*/), _nmethod_itr(ShenandoahCodeRoots::table()), - _generation(generation), _phase(phase) {} ~ShenandoahConcurrentWeakRootsEvacUpdateTask() { @@ -960,14 +957,14 @@ class ShenandoahConcurrentWeakRootsEvacUpdateTask : public WorkerTask { _vm_roots.report_num_dead(); } - void work(uint worker_id) override { + void work(uint worker_id) { ShenandoahConcurrentWorkerSession worker_session(worker_id); ShenandoahSuspendibleThreadSetJoiner sts_join; { ShenandoahEvacOOMScope oom; // jni_roots and weak_roots are OopStorage backed roots, concurrent iteration // may race against OopStorage::release() calls. - ShenandoahEvacUpdateCleanupOopStorageRootsClosure cl(_generation); + ShenandoahEvacUpdateCleanupOopStorageRootsClosure cl; _vm_roots.oops_do(&cl, worker_id); } @@ -1002,7 +999,7 @@ void ShenandoahConcurrentGC::op_weak_roots() { // Concurrent weak root processing ShenandoahTimingsTracker t(ShenandoahPhaseTimings::conc_weak_roots_work); ShenandoahGCWorkerPhase worker_phase(ShenandoahPhaseTimings::conc_weak_roots_work); - ShenandoahConcurrentWeakRootsEvacUpdateTask task(_generation, ShenandoahPhaseTimings::conc_weak_roots_work); + ShenandoahConcurrentWeakRootsEvacUpdateTask task(ShenandoahPhaseTimings::conc_weak_roots_work); heap->workers()->run_task(&task); } @@ -1108,19 +1105,19 @@ void ShenandoahConcurrentGC::op_cleanup_early() { } void ShenandoahConcurrentGC::op_evacuate() { - ShenandoahHeap::heap()->evacuate_collection_set(_generation, true /*concurrent*/); + ShenandoahHeap::heap()->evacuate_collection_set(true /*concurrent*/); } void ShenandoahConcurrentGC::op_init_update_refs() { + ShenandoahHeap* const heap = ShenandoahHeap::heap(); if (ShenandoahVerify) { - ShenandoahHeap* const heap = ShenandoahHeap::heap(); ShenandoahTimingsTracker v(ShenandoahPhaseTimings::init_update_refs_verify); - heap->verifier()->verify_before_update_refs(_generation); + heap->verifier()->verify_before_update_refs(); } } void ShenandoahConcurrentGC::op_update_refs() { - ShenandoahHeap::heap()->update_heap_references(_generation, true /*concurrent*/); + ShenandoahHeap::heap()->update_heap_references(true /*concurrent*/); } class ShenandoahUpdateThreadHandshakeClosure : public HandshakeClosure { @@ -1166,7 +1163,7 @@ void ShenandoahConcurrentGC::op_final_update_refs() { // Has to be done before cset is clear if (ShenandoahVerify) { - heap->verifier()->verify_roots_in_to_space(_generation); + heap->verifier()->verify_roots_in_to_space(); } // If we are running in generational mode and this is an aging cycle, this will also age active @@ -1201,7 +1198,7 @@ void ShenandoahConcurrentGC::op_final_update_refs() { if (ShenandoahVerify) { ShenandoahTimingsTracker v(ShenandoahPhaseTimings::final_update_refs_verify); - heap->verifier()->verify_after_update_refs(_generation); + heap->verifier()->verify_after_update_refs(); } if (VerifyAfterGC) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.hpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.hpp index 54d43416fdb3a..d81c49363a230 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.hpp @@ -47,6 +47,7 @@ class ShenandoahConcurrentGC : public ShenandoahGC { protected: ShenandoahConcurrentMark _mark; + ShenandoahGeneration* const _generation; private: ShenandoahDegenPoint _degen_point; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp index 7a195f64cbd51..005d6c42f8c55 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp @@ -56,11 +56,18 @@ class ShenandoahConcurrentMarkingTask : public WorkerTask { } void work(uint worker_id) { + ShenandoahHeap* heap = ShenandoahHeap::heap(); ShenandoahConcurrentWorkerSession worker_session(worker_id); ShenandoahWorkerTimingsTracker timer(ShenandoahPhaseTimings::conc_mark, ShenandoahPhaseTimings::ParallelMark, worker_id, true); ShenandoahSuspendibleThreadSetJoiner stsj; + // Do not use active_generation() : we must use the gc_generation() set by + // ShenandoahGCScope on the ControllerThread's stack; no safepoint may + // intervene to update active_generation, so we can't + // shenandoah_assert_generations_reconciled() here. + ShenandoahReferenceProcessor* rp = heap->gc_generation()->ref_processor(); + assert(rp != nullptr, "need reference processor"); StringDedup::Requests requests; - _cm->mark_loop(worker_id, _terminator, GENERATION, true /*cancellable*/, + _cm->mark_loop(worker_id, _terminator, rp, GENERATION, true /*cancellable*/, ShenandoahStringDedup::is_enabled() ? ENQUEUE_DEDUP : NO_DEDUP, &requests); } @@ -99,6 +106,9 @@ class ShenandoahFinalMarkingTask : public WorkerTask { ShenandoahParallelWorkerSession worker_session(worker_id); StringDedup::Requests requests; + ShenandoahReferenceProcessor* rp = heap->gc_generation()->ref_processor(); + shenandoah_assert_generations_reconciled(); + // First drain remaining SATB buffers. { ShenandoahObjToScanQueue* q = _cm->get_queue(worker_id); @@ -112,7 +122,7 @@ class ShenandoahFinalMarkingTask : public WorkerTask { ShenandoahSATBAndRemarkThreadsClosure tc(satb_mq_set); Threads::possibly_parallel_threads_do(true /* is_par */, &tc); } - _cm->mark_loop(worker_id, _terminator, GENERATION, false /*not cancellable*/, + _cm->mark_loop(worker_id, _terminator, rp, GENERATION, false /*not cancellable*/, _dedup_string ? ENQUEUE_DEDUP : NO_DEDUP, &requests); assert(_cm->task_queues()->is_empty(), "Should be empty"); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp index 2b791619d2e62..b918bf67b34b7 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.cpp @@ -46,8 +46,9 @@ #include "utilities/events.hpp" ShenandoahDegenGC::ShenandoahDegenGC(ShenandoahDegenPoint degen_point, ShenandoahGeneration* generation) : - ShenandoahGC(generation), + ShenandoahGC(), _degen_point(degen_point), + _generation(generation), _abbreviated(false) { } @@ -259,7 +260,7 @@ void ShenandoahDegenGC::op_degenerated() { } else if (has_in_place_promotions(heap)) { // We have nothing to evacuate, but there are still regions to promote in place. ShenandoahGCPhase phase(ShenandoahPhaseTimings::degen_gc_promote_regions); - ShenandoahGenerationalHeap::heap()->promote_regions_in_place(_generation, false /* concurrent*/); + ShenandoahGenerationalHeap::heap()->promote_regions_in_place(false /* concurrent*/); } // Update collector state regardless of whether there are forwarded objects @@ -299,7 +300,7 @@ void ShenandoahDegenGC::op_degenerated() { } if (ShenandoahVerify) { - heap->verifier()->verify_after_degenerated(_generation); + heap->verifier()->verify_after_degenerated(); } if (VerifyAfterGC) { @@ -336,11 +337,11 @@ void ShenandoahDegenGC::op_finish_mark() { void ShenandoahDegenGC::op_prepare_evacuation() { ShenandoahHeap* const heap = ShenandoahHeap::heap(); if (ShenandoahVerify) { - heap->verifier()->verify_roots_no_forwarded(_generation); + heap->verifier()->verify_roots_no_forwarded(); } // STW cleanup weak roots and unload classes - heap->parallel_cleaning(_generation, false /*full gc*/); + heap->parallel_cleaning(false /*full gc*/); // Prepare regions and collection set _generation->prepare_regions_and_collection_set(false /*concurrent*/); @@ -357,7 +358,7 @@ void ShenandoahDegenGC::op_prepare_evacuation() { if (!heap->collection_set()->is_empty()) { if (ShenandoahVerify) { - heap->verifier()->verify_before_evacuation(_generation); + heap->verifier()->verify_before_evacuation(); } heap->set_evacuation_in_progress(true); @@ -365,9 +366,9 @@ void ShenandoahDegenGC::op_prepare_evacuation() { } else { if (ShenandoahVerify) { if (has_in_place_promotions(heap)) { - heap->verifier()->verify_after_concmark_with_promotions(_generation); + heap->verifier()->verify_after_concmark_with_promotions(); } else { - heap->verifier()->verify_after_concmark(_generation); + heap->verifier()->verify_after_concmark(); } } @@ -387,7 +388,7 @@ void ShenandoahDegenGC::op_cleanup_early() { void ShenandoahDegenGC::op_evacuate() { ShenandoahGCPhase phase(ShenandoahPhaseTimings::degen_gc_stw_evac); - ShenandoahHeap::heap()->evacuate_collection_set(_generation, false /* concurrent*/); + ShenandoahHeap::heap()->evacuate_collection_set(false /* concurrent*/); } void ShenandoahDegenGC::op_init_update_refs() { @@ -401,7 +402,7 @@ void ShenandoahDegenGC::op_update_refs() { ShenandoahHeap* const heap = ShenandoahHeap::heap(); ShenandoahGCPhase phase(ShenandoahPhaseTimings::degen_gc_update_refs); // Handed over from concurrent update references phase - heap->update_heap_references(_generation, false /*concurrent*/); + heap->update_heap_references(false /*concurrent*/); heap->set_update_refs_in_progress(false); heap->set_has_forwarded_objects(false); @@ -415,7 +416,7 @@ void ShenandoahDegenGC::op_update_roots() { heap->update_heap_region_states(false /*concurrent*/); if (ShenandoahVerify) { - heap->verifier()->verify_after_update_refs(_generation); + heap->verifier()->verify_after_update_refs(); } if (VerifyAfterGC) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.hpp b/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.hpp index 34b9688106c90..971bd67eb0df8 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahDegeneratedGC.hpp @@ -34,11 +34,12 @@ class ShenandoahDegenGC : public ShenandoahGC { friend class VM_ShenandoahDegeneratedGC; private: const ShenandoahDegenPoint _degen_point; + ShenandoahGeneration* _generation; bool _abbreviated; public: ShenandoahDegenGC(ShenandoahDegenPoint degen_point, ShenandoahGeneration* generation); - bool collect(GCCause::Cause cause) override; + bool collect(GCCause::Cause cause); private: void vmop_degenerated(); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp index 78218f5e403f8..2e486a23363ea 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahFullGC.cpp @@ -68,7 +68,6 @@ #include "utilities/growableArray.hpp" ShenandoahFullGC::ShenandoahFullGC() : - ShenandoahGC(ShenandoahHeap::heap()->global_generation()), _gc_timer(ShenandoahHeap::heap()->gc_timer()), _preserved_marks(new PreservedMarksSet(true)) {} @@ -125,7 +124,7 @@ void ShenandoahFullGC::op_full(GCCause::Cause cause) { } // Regardless if progress was made, we record that we completed a "successful" full GC. - _generation->heuristics()->record_success_full(); + heap->global_generation()->heuristics()->record_success_full(); heap->shenandoah_policy()->record_success_full(); { @@ -142,7 +141,7 @@ void ShenandoahFullGC::do_it(GCCause::Cause gc_cause) { } if (ShenandoahVerify) { - heap->verifier()->verify_before_fullgc(_generation); + heap->verifier()->verify_before_fullgc(); } if (VerifyBeforeGC) { @@ -195,7 +194,7 @@ void ShenandoahFullGC::do_it(GCCause::Cause gc_cause) { } // d. Abandon reference discovery and clear all discovered references. - ShenandoahReferenceProcessor* rp = _generation->ref_processor(); + ShenandoahReferenceProcessor* rp = heap->global_generation()->ref_processor(); rp->abandon_partial_discovery(); // e. Sync pinned region status from the CP marks @@ -274,7 +273,7 @@ void ShenandoahFullGC::do_it(GCCause::Cause gc_cause) { heap->set_full_gc_in_progress(false); if (ShenandoahVerify) { - heap->verifier()->verify_after_fullgc(_generation); + heap->verifier()->verify_after_fullgc(); } if (VerifyAfterGC) { @@ -293,19 +292,19 @@ void ShenandoahFullGC::phase1_mark_heap() { ShenandoahHeap* heap = ShenandoahHeap::heap(); - _generation->reset_mark_bitmap(); + heap->global_generation()->reset_mark_bitmap(); assert(heap->marking_context()->is_bitmap_clear(), "sanity"); - assert(!_generation->is_mark_complete(), "sanity"); + assert(!heap->global_generation()->is_mark_complete(), "sanity"); - heap->set_unload_classes(_generation->heuristics()->can_unload_classes()); + heap->set_unload_classes(heap->global_generation()->heuristics()->can_unload_classes()); - ShenandoahReferenceProcessor* rp = _generation->ref_processor(); + ShenandoahReferenceProcessor* rp = heap->global_generation()->ref_processor(); // enable ("weak") refs discovery rp->set_soft_reference_policy(true); // forcefully purge all soft references - ShenandoahSTWMark mark(_generation, true /*full_gc*/); + ShenandoahSTWMark mark(heap->global_generation(), true /*full_gc*/); mark.mark(); - heap->parallel_cleaning(_generation, true /* full_gc */); + heap->parallel_cleaning(true /* full_gc */); if (ShenandoahHeap::heap()->mode()->is_generational()) { ShenandoahGenerationalFullGC::log_live_in_old(heap); @@ -351,12 +350,10 @@ class ShenandoahPrepareForCompactionObjectClosure : public ObjectClosure { return _empty_regions_pos; } - void do_object(oop p) override { - shenandoah_assert_mark_complete(cast_from_oop(p)); + void do_object(oop p) { assert(_from_region != nullptr, "must set before work"); - assert(_heap->global_generation()->is_mark_complete(), "marking must be finished"); - assert(_heap->marking_context()->is_marked(p), "must be marked"); - assert(!_heap->marking_context()->allocated_after_mark_start(p), "must be truly marked"); + assert(_heap->gc_generation()->complete_marking_context()->is_marked(p), "must be marked"); + assert(!_heap->gc_generation()->complete_marking_context()->allocated_after_mark_start(p), "must be truly marked"); size_t obj_size = p->size(); if (_compact_point + obj_size > _to_region->end()) { @@ -526,8 +523,12 @@ void ShenandoahFullGC::calculate_target_humongous_objects() { } class ShenandoahEnsureHeapActiveClosure: public ShenandoahHeapRegionClosure { +private: + ShenandoahHeap* const _heap; + public: - void heap_region_do(ShenandoahHeapRegion* r) override { + ShenandoahEnsureHeapActiveClosure() : _heap(ShenandoahHeap::heap()) {} + void heap_region_do(ShenandoahHeapRegion* r) { if (r->is_trash()) { r->try_recycle_under_lock(); } @@ -759,6 +760,7 @@ void ShenandoahFullGC::phase2_calculate_target_addresses(ShenandoahHeapRegionSet class ShenandoahAdjustPointersClosure : public MetadataVisitingOopIterateClosure { private: + ShenandoahHeap* const _heap; ShenandoahMarkingContext* const _ctx; template @@ -776,7 +778,8 @@ class ShenandoahAdjustPointersClosure : public MetadataVisitingOopIterateClosure public: ShenandoahAdjustPointersClosure() : - _ctx(ShenandoahHeap::heap()->global_generation()->complete_marking_context()) {} + _heap(ShenandoahHeap::heap()), + _ctx(ShenandoahHeap::heap()->gc_generation()->complete_marking_context()) {} void do_oop(oop* p) { do_oop_work(p); } void do_oop(narrowOop* p) { do_oop_work(p); } @@ -786,12 +789,15 @@ class ShenandoahAdjustPointersClosure : public MetadataVisitingOopIterateClosure class ShenandoahAdjustPointersObjectClosure : public ObjectClosure { private: + ShenandoahHeap* const _heap; ShenandoahAdjustPointersClosure _cl; public: - void do_object(oop p) override { - assert(ShenandoahHeap::heap()->global_generation()->is_mark_complete(), "marking must be complete"); - assert(ShenandoahHeap::heap()->marking_context()->is_marked(p), "must be marked"); + ShenandoahAdjustPointersObjectClosure() : + _heap(ShenandoahHeap::heap()) { + } + void do_object(oop p) { + assert(_heap->gc_generation()->complete_marking_context()->is_marked(p), "must be marked"); p->oop_iterate(&_cl); } }; @@ -807,7 +813,7 @@ class ShenandoahAdjustPointersTask : public WorkerTask { _heap(ShenandoahHeap::heap()) { } - void work(uint worker_id) override { + void work(uint worker_id) { ShenandoahParallelWorkerSession worker_session(worker_id); ShenandoahAdjustPointersObjectClosure obj_cl; ShenandoahHeapRegion* r = _regions.next(); @@ -833,7 +839,7 @@ class ShenandoahAdjustRootPointersTask : public WorkerTask { _rp(rp), _preserved_marks(preserved_marks) {} - void work(uint worker_id) override { + void work(uint worker_id) { ShenandoahParallelWorkerSession worker_session(worker_id); ShenandoahAdjustPointersClosure cl; _rp->roots_do(worker_id, &cl); @@ -867,15 +873,15 @@ void ShenandoahFullGC::phase3_update_references() { class ShenandoahCompactObjectsClosure : public ObjectClosure { private: - uint const _worker_id; + ShenandoahHeap* const _heap; + uint const _worker_id; public: - explicit ShenandoahCompactObjectsClosure(uint worker_id) : - _worker_id(worker_id) {} + ShenandoahCompactObjectsClosure(uint worker_id) : + _heap(ShenandoahHeap::heap()), _worker_id(worker_id) {} - void do_object(oop p) override { - assert(ShenandoahHeap::heap()->global_generation()->is_mark_complete(), "marking must be finished"); - assert(ShenandoahHeap::heap()->marking_context()->is_marked(p), "must be marked"); + void do_object(oop p) { + assert(_heap->gc_generation()->complete_marking_context()->is_marked(p), "must be marked"); size_t size = p->size(); if (FullGCForwarding::is_forwarded(p)) { HeapWord* compact_from = cast_from_oop(p); @@ -902,7 +908,7 @@ class ShenandoahCompactObjectsTask : public WorkerTask { _worker_slices(worker_slices) { } - void work(uint worker_id) override { + void work(uint worker_id) { ShenandoahParallelWorkerSession worker_session(worker_id); ShenandoahHeapRegionSetIterator slice(_worker_slices[worker_id]); @@ -939,7 +945,7 @@ class ShenandoahPostCompactClosure : public ShenandoahHeapRegionClosure { _heap->free_set()->clear(); } - void heap_region_do(ShenandoahHeapRegion* r) override { + void heap_region_do(ShenandoahHeapRegion* r) { assert (!r->is_cset(), "cset regions should have been demoted already"); // Need to reset the complete-top-at-mark-start pointer here because @@ -948,7 +954,7 @@ class ShenandoahPostCompactClosure : public ShenandoahHeapRegionClosure { // NOTE: See blurb at ShenandoahMCResetCompleteBitmapTask on why we need to skip // pinned regions. if (!r->is_pinned()) { - _heap->marking_context()->reset_top_at_mark_start(r); + _heap->gc_generation()->complete_marking_context()->reset_top_at_mark_start(r); } size_t live = r->used(); @@ -1073,7 +1079,7 @@ void ShenandoahFullGC::compact_humongous_objects() { // we need to remain able to walk pinned regions. // Since pinned region do not move and don't get compacted, we will get holes with // unreachable objects in them (which may have pointers to unloaded Klasses and thus -// cannot be iterated over using oop->size()). The only way to safely iterate over those is using +// cannot be iterated over using oop->size(). The only way to safely iterate over those is using // a valid marking bitmap and valid TAMS pointer. This class only resets marking // bitmaps for un-pinned regions, and later we only reset TAMS for unpinned regions. class ShenandoahMCResetCompleteBitmapTask : public WorkerTask { @@ -1085,12 +1091,11 @@ class ShenandoahMCResetCompleteBitmapTask : public WorkerTask { WorkerTask("Shenandoah Reset Bitmap") { } - void work(uint worker_id) override { + void work(uint worker_id) { ShenandoahParallelWorkerSession worker_session(worker_id); ShenandoahHeapRegion* region = _regions.next(); ShenandoahHeap* heap = ShenandoahHeap::heap(); - ShenandoahMarkingContext* const ctx = heap->marking_context(); - assert(heap->global_generation()->is_mark_complete(), "Marking must be complete"); + ShenandoahMarkingContext* const ctx = heap->gc_generation()->complete_marking_context(); while (region != nullptr) { if (heap->is_bitmap_slice_committed(region) && !region->is_pinned() && region->has_live()) { ctx->clear_bitmap(region); @@ -1158,7 +1163,7 @@ ShenandoahGenerationalHeap::TransferResult ShenandoahFullGC::phase5_epilog() { heap->free_set()->finish_rebuild(young_cset_regions, old_cset_regions, num_old); // Set mark incomplete because the marking bitmaps have been reset except pinned regions. - _generation->set_mark_incomplete(); + heap->global_generation()->set_mark_incomplete(); heap->clear_cancelled_gc(); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahFullGC.hpp b/src/hotspot/share/gc/shenandoah/shenandoahFullGC.hpp index 8b8244f2ce3ab..b0b8c7bf0c599 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahFullGC.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahFullGC.hpp @@ -68,7 +68,7 @@ class ShenandoahFullGC : public ShenandoahGC { public: ShenandoahFullGC(); ~ShenandoahFullGC(); - bool collect(GCCause::Cause cause) override; + bool collect(GCCause::Cause cause); private: // GC entries diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGC.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGC.hpp index 7182665f2e3a1..f08bdce0a2025 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGC.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGC.hpp @@ -44,8 +44,6 @@ * Full GC --------> (finish) */ -class ShenandoahGeneration; - class ShenandoahGC : public StackObj { public: // Fail point from concurrent GC @@ -59,17 +57,12 @@ class ShenandoahGC : public StackObj { _DEGENERATED_LIMIT }; - explicit ShenandoahGC(ShenandoahGeneration* generation) : _generation(generation) {} - // Returns false if the collection was cancelled, true otherwise. virtual bool collect(GCCause::Cause cause) = 0; static const char* degen_point_to_string(ShenandoahDegenPoint point); - ShenandoahGeneration* generation() const { return _generation; } protected: static void update_roots(bool full_gc); - - ShenandoahGeneration* _generation; }; #endif // SHARE_GC_SHENANDOAH_SHENANDOAHGC_HPP diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp index d2e25176c1fce..e6597b3c1e49c 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp @@ -142,11 +142,6 @@ class ShenandoahGeneration : public CHeapObj, public ShenandoahSpaceInfo { size_t soft_available() const override; size_t bytes_allocated_since_gc_start() const override; - - // Reset the bytes allocated within this generation since the start of GC. The argument initial_bytes_allocated - // is normally zero. In the case that some memory was allocated following the last allocation rate sample that - // precedes the start of GC, the number of bytes allocated is supplied as the initial value of bytes_allocated_since_gc_start. - // We will behave as if these bytes were allocated after the start of GC. void reset_bytes_allocated_since_gc_start(size_t initial_bytes_allocated); void increase_allocated(size_t bytes); @@ -203,7 +198,7 @@ class ShenandoahGeneration : public CHeapObj, public ShenandoahSpaceInfo { bool is_bitmap_clear(); // We need to track the status of marking for different generations. - bool is_mark_complete() const { return _is_marking_complete.is_set(); } + bool is_mark_complete() { return _is_marking_complete.is_set(); } virtual void set_mark_complete(); virtual void set_mark_incomplete(); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.cpp index ccabdb7b9daa9..971129beea807 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.cpp @@ -50,12 +50,10 @@ class ShenandoahConcurrentEvacuator : public ObjectClosure { }; ShenandoahGenerationalEvacuationTask::ShenandoahGenerationalEvacuationTask(ShenandoahGenerationalHeap* heap, - ShenandoahGeneration* generation, ShenandoahRegionIterator* iterator, bool concurrent, bool only_promote_regions) : WorkerTask("Shenandoah Evacuation"), _heap(heap), - _generation(generation), _regions(iterator), _concurrent(concurrent), _only_promote_regions(only_promote_regions) @@ -171,12 +169,13 @@ void ShenandoahGenerationalEvacuationTask::maybe_promote_region(ShenandoahHeapRe // We identify the entirety of the region as DIRTY to force the next remembered set scan to identify the "interesting pointers" // contained herein. void ShenandoahGenerationalEvacuationTask::promote_in_place(ShenandoahHeapRegion* region) { - assert(!_generation->is_old(), "Sanity check"); + assert(!_heap->gc_generation()->is_old(), "Sanity check"); ShenandoahMarkingContext* const marking_context = _heap->young_generation()->complete_marking_context(); HeapWord* const tams = marking_context->top_at_mark_start(region); { const size_t old_garbage_threshold = (ShenandoahHeapRegion::region_size_bytes() * ShenandoahOldGarbageThreshold) / 100; + shenandoah_assert_generations_reconciled(); assert(!_heap->is_concurrent_old_mark_in_progress(), "Cannot promote in place during old marking"); assert(region->garbage_before_padded_for_promote() < old_garbage_threshold, "Region %zu has too much garbage for promotion", region->index()); assert(region->is_young(), "Only young regions can be promoted"); @@ -260,7 +259,8 @@ void ShenandoahGenerationalEvacuationTask::promote_in_place(ShenandoahHeapRegion void ShenandoahGenerationalEvacuationTask::promote_humongous(ShenandoahHeapRegion* region) { ShenandoahMarkingContext* marking_context = _heap->marking_context(); oop obj = cast_to_oop(region->bottom()); - assert(_generation->is_mark_complete(), "sanity"); + assert(_heap->gc_generation()->is_mark_complete(), "sanity"); + shenandoah_assert_generations_reconciled(); assert(region->is_young(), "Only young regions can be promoted"); assert(region->is_humongous_start(), "Should not promote humongous continuation in isolation"); assert(_heap->is_tenurable(region), "Only promote regions that are sufficiently aged"); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.hpp index de47184ffffc3..0c402d6c90a58 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.hpp @@ -36,14 +36,12 @@ class ShenandoahRegionIterator; class ShenandoahGenerationalEvacuationTask : public WorkerTask { private: ShenandoahGenerationalHeap* const _heap; - ShenandoahGeneration* const _generation; ShenandoahRegionIterator* _regions; bool _concurrent; bool _only_promote_regions; public: ShenandoahGenerationalEvacuationTask(ShenandoahGenerationalHeap* sh, - ShenandoahGeneration* generation, ShenandoahRegionIterator* iterator, bool concurrent, bool only_promote_regions); void work(uint worker_id) override; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.cpp index 8d8091472fcbb..c4a7408e03243 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.cpp @@ -53,7 +53,8 @@ void assert_usage_not_more_than_regions_used(ShenandoahGeneration* generation) { void ShenandoahGenerationalFullGC::prepare() { auto heap = ShenandoahGenerationalHeap::heap(); // Since we may arrive here from degenerated GC failure of either young or old, establish generation as GLOBAL. - heap->set_active_generation(heap->global_generation()); + heap->set_gc_generation(heap->global_generation()); + heap->set_active_generation(); // No need for old_gen->increase_used() as this was done when plabs were allocated. heap->reset_generation_reserves(); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp index bc653b030a8ca..34f217ada250b 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp @@ -178,15 +178,15 @@ bool ShenandoahGenerationalHeap::requires_barriers(stackChunkOop obj) const { return false; } -void ShenandoahGenerationalHeap::evacuate_collection_set(ShenandoahGeneration* generation, bool concurrent) { +void ShenandoahGenerationalHeap::evacuate_collection_set(bool concurrent) { ShenandoahRegionIterator regions; - ShenandoahGenerationalEvacuationTask task(this, generation, ®ions, concurrent, false /* only promote regions */); + ShenandoahGenerationalEvacuationTask task(this, ®ions, concurrent, false /* only promote regions */); workers()->run_task(&task); } -void ShenandoahGenerationalHeap::promote_regions_in_place(ShenandoahGeneration* generation, bool concurrent) { +void ShenandoahGenerationalHeap::promote_regions_in_place(bool concurrent) { ShenandoahRegionIterator regions; - ShenandoahGenerationalEvacuationTask task(this, generation, ®ions, concurrent, true /* only promote regions */); + ShenandoahGenerationalEvacuationTask task(this, ®ions, concurrent, true /* only promote regions */); workers()->run_task(&task); } @@ -757,27 +757,23 @@ void ShenandoahGenerationalHeap::coalesce_and_fill_old_regions(bool concurrent) template class ShenandoahGenerationalUpdateHeapRefsTask : public WorkerTask { private: - // For update refs, _generation will be young or global. Mixed collections use the young generation. - ShenandoahGeneration* _generation; ShenandoahGenerationalHeap* _heap; ShenandoahRegionIterator* _regions; ShenandoahRegionChunkIterator* _work_chunks; public: - ShenandoahGenerationalUpdateHeapRefsTask(ShenandoahGeneration* generation, - ShenandoahRegionIterator* regions, - ShenandoahRegionChunkIterator* work_chunks) : + explicit ShenandoahGenerationalUpdateHeapRefsTask(ShenandoahRegionIterator* regions, + ShenandoahRegionChunkIterator* work_chunks) : WorkerTask("Shenandoah Update References"), - _generation(generation), _heap(ShenandoahGenerationalHeap::heap()), _regions(regions), _work_chunks(work_chunks) { - const bool old_bitmap_stable = _heap->old_generation()->is_mark_complete(); + bool old_bitmap_stable = _heap->old_generation()->is_mark_complete(); log_debug(gc, remset)("Update refs, scan remembered set using bitmap: %s", BOOL_TO_STR(old_bitmap_stable)); } - void work(uint worker_id) override { + void work(uint worker_id) { if (CONCURRENT) { ShenandoahConcurrentWorkerSession worker_session(worker_id); ShenandoahSuspendibleThreadSetJoiner stsj; @@ -807,8 +803,10 @@ class ShenandoahGenerationalUpdateHeapRefsTask : public WorkerTask { // If !CONCURRENT, there's no value in expanding Mutator free set ShenandoahHeapRegion* r = _regions->next(); - // We update references for global, mixed, and young collections. - assert(_generation->is_mark_complete(), "Expected complete marking"); + // We update references for global, old, and young collections. + ShenandoahGeneration* const gc_generation = _heap->gc_generation(); + shenandoah_assert_generations_reconciled(); + assert(gc_generation->is_mark_complete(), "Expected complete marking"); ShenandoahMarkingContext* const ctx = _heap->marking_context(); bool is_mixed = _heap->collection_set()->has_old_regions(); while (r != nullptr) { @@ -820,7 +818,7 @@ class ShenandoahGenerationalUpdateHeapRefsTask : public WorkerTask { if (r->is_young()) { _heap->marked_object_oop_iterate(r, &cl, update_watermark); } else if (r->is_old()) { - if (_generation->is_global()) { + if (gc_generation->is_global()) { _heap->marked_object_oop_iterate(r, &cl, update_watermark); } @@ -849,7 +847,7 @@ class ShenandoahGenerationalUpdateHeapRefsTask : public WorkerTask { r = _regions->next(); } - if (_generation->is_young()) { + if (!gc_generation->is_global()) { // Since this is generational and not GLOBAL, we have to process the remembered set. There's no remembered // set processing if not in generational mode or if GLOBAL mode. @@ -963,15 +961,15 @@ class ShenandoahGenerationalUpdateHeapRefsTask : public WorkerTask { } }; -void ShenandoahGenerationalHeap::update_heap_references(ShenandoahGeneration* generation, bool concurrent) { +void ShenandoahGenerationalHeap::update_heap_references(bool concurrent) { assert(!is_full_gc_in_progress(), "Only for concurrent and degenerated GC"); const uint nworkers = workers()->active_workers(); ShenandoahRegionChunkIterator work_list(nworkers); if (concurrent) { - ShenandoahGenerationalUpdateHeapRefsTask task(generation, &_update_refs_iterator, &work_list); + ShenandoahGenerationalUpdateHeapRefsTask task(&_update_refs_iterator, &work_list); workers()->run_task(&task); } else { - ShenandoahGenerationalUpdateHeapRefsTask task(generation, &_update_refs_iterator, &work_list); + ShenandoahGenerationalUpdateHeapRefsTask task(&_update_refs_iterator, &work_list); workers()->run_task(&task); } @@ -1046,7 +1044,7 @@ class ShenandoahUpdateRegionAges : public ShenandoahHeapRegionClosure { void ShenandoahGenerationalHeap::final_update_refs_update_region_states() { ShenandoahSynchronizePinnedRegionStates pins; - ShenandoahUpdateRegionAges ages(marking_context()); + ShenandoahUpdateRegionAges ages(active_generation()->complete_marking_context()); auto cl = ShenandoahCompositeRegionClosure::of(pins, ages); parallel_heap_region_iterate(&cl); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.hpp index d3584a6f9a01a..6960562b31d80 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.hpp @@ -88,11 +88,8 @@ class ShenandoahGenerationalHeap : public ShenandoahHeap { oop evacuate_object(oop p, Thread* thread) override; oop try_evacuate_object(oop p, Thread* thread, ShenandoahHeapRegion* from_region, ShenandoahAffiliation target_gen); - - // In the generational mode, we will use these two functions for young, mixed, and global collections. - // For young and mixed, the generation argument will be the young generation, otherwise it will be the global generation. - void evacuate_collection_set(ShenandoahGeneration* generation, bool concurrent) override; - void promote_regions_in_place(ShenandoahGeneration* generation, bool concurrent); + void evacuate_collection_set(bool concurrent) override; + void promote_regions_in_place(bool concurrent); size_t plab_min_size() const { return _min_plab_size; } size_t plab_max_size() const { return _max_plab_size; } @@ -102,9 +99,7 @@ class ShenandoahGenerationalHeap : public ShenandoahHeap { // ---------- Update References // - // In the generational mode, we will use this function for young, mixed, and global collections. - // For young and mixed, the generation argument will be the young generation, otherwise it will be the global generation. - void update_heap_references(ShenandoahGeneration* generation, bool concurrent) override; + void update_heap_references(bool concurrent) override; void final_update_refs_update_region_states() override; private: diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp index cb22c794d8554..b2fd32d2fd0b9 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -529,6 +529,7 @@ void ShenandoahHeap::initialize_heuristics() { ShenandoahHeap::ShenandoahHeap(ShenandoahCollectorPolicy* policy) : CollectedHeap(), + _gc_generation(nullptr), _active_generation(nullptr), _initial_size(0), _committed(0), @@ -1256,8 +1257,7 @@ class ShenandoahPrepareForUpdateRefsHandshakeClosure : public HandshakeClosure { ShenandoahGCStatePropagatorHandshakeClosure _propagator; }; -void ShenandoahHeap::evacuate_collection_set(ShenandoahGeneration* generation, bool concurrent) { - assert(generation->is_global(), "Only global generation expected here"); +void ShenandoahHeap::evacuate_collection_set(bool concurrent) { ShenandoahEvacuationTask task(this, _collection_set, concurrent); workers()->run_task(&task); } @@ -1576,8 +1576,8 @@ void ShenandoahHeap::collect_as_vm_thread(GCCause::Cause cause) { // cycle. We _could_ cancel the concurrent cycle and then try to run a cycle directly // on the VM thread, but this would confuse the control thread mightily and doesn't // seem worth the trouble. Instead, we will have the caller thread run (and wait for) a - // concurrent cycle in the prologue of the heap inspect/dump operation (see VM_HeapDumper::doit_prologue). - // This is how other concurrent collectors in the JVM handle this scenario as well. + // concurrent cycle in the prologue of the heap inspect/dump operation. This is how + // other concurrent collectors in the JVM handle this scenario as well. assert(Thread::current()->is_VM_thread(), "Should be the VM thread"); guarantee(cause == GCCause::_heap_dump || cause == GCCause::_heap_inspection, "Invalid cause"); } @@ -1587,10 +1587,7 @@ void ShenandoahHeap::collect(GCCause::Cause cause) { } void ShenandoahHeap::do_full_collection(bool clear_all_soft_refs) { - // This method is only called by `CollectedHeap::collect_as_vm_thread`, which we have - // overridden to do nothing. See the comment there for an explanation of how heap inspections - // work for Shenandoah. - ShouldNotReachHere(); + //assert(false, "Shouldn't need to do full collections"); } HeapWord* ShenandoahHeap::block_start(const void* addr) const { @@ -1659,11 +1656,17 @@ void ShenandoahHeap::print_tracing_info() const { } } +void ShenandoahHeap::set_gc_generation(ShenandoahGeneration* generation) { + shenandoah_assert_control_or_vm_thread_at_safepoint(); + _gc_generation = generation; +} + // Active generation may only be set by the VM thread at a safepoint. -void ShenandoahHeap::set_active_generation(ShenandoahGeneration* generation) { +void ShenandoahHeap::set_active_generation() { assert(Thread::current()->is_VM_thread(), "Only the VM Thread"); assert(SafepointSynchronize::is_at_safepoint(), "Only at a safepoint!"); - _active_generation = generation; + assert(_gc_generation != nullptr, "Will set _active_generation to nullptr"); + _active_generation = _gc_generation; } void ShenandoahHeap::on_cycle_start(GCCause::Cause cause, ShenandoahGeneration* generation) { @@ -1672,14 +1675,17 @@ void ShenandoahHeap::on_cycle_start(GCCause::Cause cause, ShenandoahGeneration* const GCCause::Cause current = gc_cause(); assert(current == GCCause::_no_gc, "Over-writing cause: %s, with: %s", GCCause::to_string(current), GCCause::to_string(cause)); + assert(_gc_generation == nullptr, "Over-writing _gc_generation"); set_gc_cause(cause); + set_gc_generation(generation); generation->heuristics()->record_cycle_start(); } void ShenandoahHeap::on_cycle_end(ShenandoahGeneration* generation) { assert(gc_cause() != GCCause::_no_gc, "cause wasn't set"); + assert(_gc_generation != nullptr, "_gc_generation wasn't set"); generation->heuristics()->record_cycle_end(); if (mode()->is_generational() && generation->is_global()) { @@ -1688,13 +1694,14 @@ void ShenandoahHeap::on_cycle_end(ShenandoahGeneration* generation) { old_generation()->heuristics()->record_cycle_end(); } + set_gc_generation(nullptr); set_gc_cause(GCCause::_no_gc); } void ShenandoahHeap::verify(VerifyOption vo) { if (ShenandoahSafepoint::is_at_shenandoah_safepoint()) { if (ShenandoahVerify) { - verifier()->verify_generic(active_generation(), vo); + verifier()->verify_generic(vo); } else { // TODO: Consider allocating verification bitmaps on demand, // and turn this on unconditionally. @@ -2054,13 +2061,14 @@ void ShenandoahHeap::do_class_unloading() { } } -void ShenandoahHeap::stw_weak_refs(ShenandoahGeneration* generation, bool full_gc) { +void ShenandoahHeap::stw_weak_refs(bool full_gc) { // Weak refs processing ShenandoahPhaseTimings::Phase phase = full_gc ? ShenandoahPhaseTimings::full_gc_weakrefs : ShenandoahPhaseTimings::degen_gc_weakrefs; ShenandoahTimingsTracker t(phase); ShenandoahGCWorkerPhase worker_phase(phase); - generation->ref_processor()->process_references(phase, workers(), false /* concurrent */); + shenandoah_assert_generations_reconciled(); + gc_generation()->ref_processor()->process_references(phase, workers(), false /* concurrent */); } void ShenandoahHeap::prepare_update_heap_references() { @@ -2301,13 +2309,13 @@ void ShenandoahHeap::stw_process_weak_roots(bool full_gc) { } } -void ShenandoahHeap::parallel_cleaning(ShenandoahGeneration* generation, bool full_gc) { +void ShenandoahHeap::parallel_cleaning(bool full_gc) { assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint"); assert(is_stw_gc_in_progress(), "Only for Degenerated and Full GC"); ShenandoahGCPhase phase(full_gc ? ShenandoahPhaseTimings::full_gc_purge : ShenandoahPhaseTimings::degen_gc_purge); - stw_weak_refs(generation, full_gc); + stw_weak_refs(full_gc); stw_process_weak_roots(full_gc); stw_unload_classes(full_gc); } @@ -2415,8 +2423,11 @@ void ShenandoahHeap::sync_pinned_region_status() { void ShenandoahHeap::assert_pinned_region_status() { for (size_t i = 0; i < num_regions(); i++) { ShenandoahHeapRegion* r = get_region(i); - assert((r->is_pinned() && r->pin_count() > 0) || (!r->is_pinned() && r->pin_count() == 0), - "Region %zu pinning status is inconsistent", i); + shenandoah_assert_generations_reconciled(); + if (gc_generation()->contains(r)) { + assert((r->is_pinned() && r->pin_count() > 0) || (!r->is_pinned() && r->pin_count() == 0), + "Region %zu pinning status is inconsistent", i); + } } } #endif @@ -2519,8 +2530,7 @@ class ShenandoahUpdateHeapRefsTask : public WorkerTask { } }; -void ShenandoahHeap::update_heap_references(ShenandoahGeneration* generation, bool concurrent) { - assert(generation->is_global(), "Should only get global generation here"); +void ShenandoahHeap::update_heap_references(bool concurrent) { assert(!is_full_gc_in_progress(), "Only for concurrent and degenerated GC"); if (concurrent) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp index d6bc17b844bfa..8bcb04e5766c8 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.hpp @@ -145,10 +145,17 @@ class ShenandoahHeap : public CollectedHeap { private: ShenandoahHeapLock _lock; + // Indicates the generation whose collection is in + // progress. Mutator threads aren't allowed to read + // this field. + ShenandoahGeneration* _gc_generation; + // This is set and cleared by only the VMThread - // at each STW pause (safepoint) to the value given to the VM operation. - // This allows the value to be always consistently + // at each STW pause (safepoint) to the value seen in + // _gc_generation. This allows the value to be always consistently // seen by all mutators as well as all GC worker threads. + // In that sense, it's a stable snapshot of _gc_generation that is + // updated at each STW pause associated with a ShenandoahVMOp. ShenandoahGeneration* _active_generation; protected: @@ -160,13 +167,25 @@ class ShenandoahHeap : public CollectedHeap { return &_lock; } + ShenandoahGeneration* gc_generation() const { + // We don't want this field read by a mutator thread + assert(!Thread::current()->is_Java_thread(), "Not allowed"); + // value of _gc_generation field, see above + return _gc_generation; + } + ShenandoahGeneration* active_generation() const { // value of _active_generation field, see above return _active_generation; } - // Update the _active_generation field: can only be called at a safepoint by the VMThread. - void set_active_generation(ShenandoahGeneration* generation); + // Set the _gc_generation field + void set_gc_generation(ShenandoahGeneration* generation); + + // Copy the value in the _gc_generation field into + // the _active_generation field: can only be called at + // a safepoint by the VMThread. + void set_active_generation(); ShenandoahHeuristics* heuristics(); @@ -463,7 +482,7 @@ class ShenandoahHeap : public CollectedHeap { // GC support // Evacuation - virtual void evacuate_collection_set(ShenandoahGeneration* generation, bool concurrent); + virtual void evacuate_collection_set(bool concurrent); // Concurrent root processing void prepare_concurrent_roots(); void finish_concurrent_roots(); @@ -478,7 +497,7 @@ class ShenandoahHeap : public CollectedHeap { // Turn off weak roots flag, purge old satb buffers in generational mode void concurrent_final_roots(HandshakeClosure* handshake_closure = nullptr); - virtual void update_heap_references(ShenandoahGeneration* generation, bool concurrent); + virtual void update_heap_references(bool concurrent); // Final update region states void update_heap_region_states(bool concurrent); virtual void final_update_refs_update_region_states(); @@ -586,12 +605,12 @@ class ShenandoahHeap : public CollectedHeap { bool unload_classes() const; // Perform STW class unloading and weak root cleaning - void parallel_cleaning(ShenandoahGeneration* generation, bool full_gc); + void parallel_cleaning(bool full_gc); private: void stw_unload_classes(bool full_gc); void stw_process_weak_roots(bool full_gc); - void stw_weak_refs(ShenandoahGeneration* generation, bool full_gc); + void stw_weak_refs(bool full_gc); inline void assert_lock_for_affiliation(ShenandoahAffiliation orig_affiliation, ShenandoahAffiliation new_affiliation); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp index ca0f7460d542e..df45a59433ec7 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.cpp @@ -315,9 +315,9 @@ void ShenandoahHeapRegion::make_trash_immediate() { // On this path, we know there are no marked objects in the region, // tell marking context about it to bypass bitmap resets. - const ShenandoahHeap* heap = ShenandoahHeap::heap(); - assert(heap->generation_for(affiliation())->is_mark_complete(), "Marking should be complete here."); - heap->marking_context()->reset_top_bitmap(this); + assert(ShenandoahHeap::heap()->gc_generation()->is_mark_complete(), "Marking should be complete here."); + shenandoah_assert_generations_reconciled(); + ShenandoahHeap::heap()->marking_context()->reset_top_bitmap(this); } void ShenandoahHeapRegion::make_empty() { @@ -461,9 +461,9 @@ bool ShenandoahHeapRegion::oop_coalesce_and_fill(bool cancellable) { ShenandoahGenerationalHeap* heap = ShenandoahGenerationalHeap::heap(); ShenandoahMarkingContext* marking_context = heap->marking_context(); - // Expect marking to be completed for the old generation before we fill in unmarked objects - assert(heap->old_generation()->is_mark_complete(), "sanity"); - assert(is_old(), "Only need to coalesce and fill old regions"); + // Expect marking to be completed before these threads invoke this service. + assert(heap->gc_generation()->is_mark_complete(), "sanity"); + shenandoah_assert_generations_reconciled(); // All objects above TAMS are considered live even though their mark bits will not be set. Note that young- // gen evacuations that interrupt a long-running old-gen concurrent mark may promote objects into old-gen diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMark.cpp b/src/hotspot/share/gc/shenandoah/shenandoahMark.cpp index a3c28e2c6d370..2a4149ee44dc4 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMark.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMark.cpp @@ -55,10 +55,10 @@ ShenandoahMark::ShenandoahMark(ShenandoahGeneration* generation) : } template -void ShenandoahMark::mark_loop_prework(uint w, TaskTerminator *t, StringDedup::Requests* const req, bool update_refs) { +void ShenandoahMark::mark_loop_prework(uint w, TaskTerminator *t, ShenandoahReferenceProcessor *rp, StringDedup::Requests* const req, bool update_refs) { ShenandoahObjToScanQueue* q = get_queue(w); ShenandoahObjToScanQueue* old_q = get_old_queue(w); - ShenandoahReferenceProcessor *rp = _generation->ref_processor(); + ShenandoahHeap* const heap = ShenandoahHeap::heap(); ShenandoahLiveData* ld = heap->get_liveness_cache(w); @@ -78,22 +78,22 @@ void ShenandoahMark::mark_loop_prework(uint w, TaskTerminator *t, StringDedup::R } template -void ShenandoahMark::mark_loop(uint worker_id, TaskTerminator* terminator, - ShenandoahGenerationType generation_type, StringDedup::Requests* const req) { +void ShenandoahMark::mark_loop(uint worker_id, TaskTerminator* terminator, ShenandoahReferenceProcessor *rp, + ShenandoahGenerationType generation, StringDedup::Requests* const req) { bool update_refs = ShenandoahHeap::heap()->has_forwarded_objects(); - switch (generation_type) { + switch (generation) { case YOUNG: - mark_loop_prework(worker_id, terminator, req, update_refs); + mark_loop_prework(worker_id, terminator, rp, req, update_refs); break; case OLD: // Old generation collection only performs marking, it should not update references. - mark_loop_prework(worker_id, terminator, req, false); + mark_loop_prework(worker_id, terminator, rp, req, false); break; case GLOBAL: - mark_loop_prework(worker_id, terminator, req, update_refs); + mark_loop_prework(worker_id, terminator, rp, req, update_refs); break; case NON_GEN: - mark_loop_prework(worker_id, terminator, req, update_refs); + mark_loop_prework(worker_id, terminator, rp, req, update_refs); break; default: ShouldNotReachHere(); @@ -101,30 +101,30 @@ void ShenandoahMark::mark_loop(uint worker_id, TaskTerminator* terminator, } } -void ShenandoahMark::mark_loop(uint worker_id, TaskTerminator* terminator, ShenandoahGenerationType generation_type, - bool cancellable, StringDedupMode dedup_mode, StringDedup::Requests* const req) { +void ShenandoahMark::mark_loop(uint worker_id, TaskTerminator* terminator, ShenandoahReferenceProcessor *rp, + ShenandoahGenerationType generation, bool cancellable, StringDedupMode dedup_mode, StringDedup::Requests* const req) { if (cancellable) { switch(dedup_mode) { case NO_DEDUP: - mark_loop(worker_id, terminator, generation_type, req); + mark_loop(worker_id, terminator, rp, generation, req); break; case ENQUEUE_DEDUP: - mark_loop(worker_id, terminator, generation_type, req); + mark_loop(worker_id, terminator, rp, generation, req); break; case ALWAYS_DEDUP: - mark_loop(worker_id, terminator, generation_type, req); + mark_loop(worker_id, terminator, rp, generation, req); break; } } else { switch(dedup_mode) { case NO_DEDUP: - mark_loop(worker_id, terminator, generation_type, req); + mark_loop(worker_id, terminator, rp, generation, req); break; case ENQUEUE_DEDUP: - mark_loop(worker_id, terminator, generation_type, req); + mark_loop(worker_id, terminator, rp, generation, req); break; case ALWAYS_DEDUP: - mark_loop(worker_id, terminator, generation_type, req); + mark_loop(worker_id, terminator, rp, generation, req); break; } } @@ -139,8 +139,12 @@ void ShenandoahMark::mark_loop_work(T* cl, ShenandoahLiveData* live_data, uint w ShenandoahObjToScanQueue* q; ShenandoahMarkTask t; - assert(_generation->type() == GENERATION, "Sanity: %d != %d", _generation->type(), GENERATION); - _generation->ref_processor()->set_mark_closure(worker_id, cl); + // Do not use active_generation() : we must use the gc_generation() set by + // ShenandoahGCScope on the ControllerThread's stack; no safepoint may + // intervene to update active_generation, so we can't + // shenandoah_assert_generations_reconciled() here. + assert(heap->gc_generation()->type() == GENERATION, "Sanity: %d != %d", heap->gc_generation()->type(), GENERATION); + heap->gc_generation()->ref_processor()->set_mark_closure(worker_id, cl); /* * Process outstanding queues, if any. diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMark.hpp b/src/hotspot/share/gc/shenandoah/shenandoahMark.hpp index 2fbb106f4d7c8..4aef14f2c9aba 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMark.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMark.hpp @@ -41,6 +41,7 @@ enum StringDedupMode { }; class ShenandoahMarkingContext; +class ShenandoahReferenceProcessor; // Base class for mark // Mark class does not maintain states. Instead, mark states are @@ -71,7 +72,7 @@ class ShenandoahMark: public StackObj { inline ShenandoahObjToScanQueue* get_queue(uint index) const; inline ShenandoahObjToScanQueue* get_old_queue(uint index) const; - ShenandoahGeneration* generation() const { return _generation; }; + inline ShenandoahGeneration* generation() { return _generation; }; private: // ---------- Marking loop and tasks @@ -92,7 +93,7 @@ class ShenandoahMark: public StackObj { void mark_loop_work(T* cl, ShenandoahLiveData* live_data, uint worker_id, TaskTerminator *t, StringDedup::Requests* const req); template - void mark_loop_prework(uint worker_id, TaskTerminator *terminator, StringDedup::Requests* const req, bool update_refs); + void mark_loop_prework(uint worker_id, TaskTerminator *terminator, ShenandoahReferenceProcessor *rp, StringDedup::Requests* const req, bool update_refs); template static bool in_generation(ShenandoahHeap* const heap, oop obj); @@ -108,11 +109,11 @@ class ShenandoahMark: public StackObj { inline void dedup_string(oop obj, StringDedup::Requests* const req); protected: template - void mark_loop(uint worker_id, TaskTerminator* terminator, ShenandoahGenerationType generation_type, - StringDedup::Requests* const req); + void mark_loop(uint worker_id, TaskTerminator* terminator, ShenandoahReferenceProcessor *rp, + ShenandoahGenerationType generation, StringDedup::Requests* const req); - void mark_loop(uint worker_id, TaskTerminator* terminator, ShenandoahGenerationType generation_type, - bool cancellable, StringDedupMode dedup_mode, StringDedup::Requests* const req); + void mark_loop(uint worker_id, TaskTerminator* terminator, ShenandoahReferenceProcessor *rp, + ShenandoahGenerationType generation, bool cancellable, StringDedupMode dedup_mode, StringDedup::Requests* const req); }; #endif // SHARE_GC_SHENANDOAH_SHENANDOAHMARK_HPP diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.cpp b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.cpp index 40eee8c342bad..0babeaffd3e0e 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.cpp @@ -74,8 +74,8 @@ void ShenandoahMarkingContext::initialize_top_at_mark_start(ShenandoahHeapRegion _top_at_mark_starts_base[idx] = bottom; _top_bitmaps[idx] = bottom; - log_debug(gc, mark)("SMC:initialize_top_at_mark_start for Region %zu, TAMS: " PTR_FORMAT ", TopOfBitMap: " PTR_FORMAT, - r->index(), p2i(bottom), p2i(r->end())); + log_debug(gc)("SMC:initialize_top_at_mark_start for Region %zu, TAMS: " PTR_FORMAT ", TopOfBitMap: " PTR_FORMAT, + r->index(), p2i(bottom), p2i(r->end())); } HeapWord* ShenandoahMarkingContext::top_bitmap(ShenandoahHeapRegion* r) { @@ -86,8 +86,8 @@ void ShenandoahMarkingContext::clear_bitmap(ShenandoahHeapRegion* r) { HeapWord* bottom = r->bottom(); HeapWord* top_bitmap = _top_bitmaps[r->index()]; - log_debug(gc, mark)("SMC:clear_bitmap for %s Region %zu, top_bitmap: " PTR_FORMAT, - r->affiliation_name(), r->index(), p2i(top_bitmap)); + log_debug(gc)("SMC:clear_bitmap for %s Region %zu, top_bitmap: " PTR_FORMAT, + r->affiliation_name(), r->index(), p2i(top_bitmap)); if (top_bitmap > bottom) { _mark_bit_map.clear_range_large(MemRegion(bottom, top_bitmap)); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.inline.hpp index bff4afc9ce9d0..e3ba774283c18 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.inline.hpp @@ -104,8 +104,8 @@ inline void ShenandoahMarkingContext::capture_top_at_mark_start(ShenandoahHeapRe "Region %zu, bitmap should be clear while adjusting TAMS: " PTR_FORMAT " -> " PTR_FORMAT, idx, p2i(old_tams), p2i(new_tams)); - log_debug(gc, mark)("Capturing TAMS for %s Region %zu, was: " PTR_FORMAT ", now: " PTR_FORMAT, - r->affiliation_name(), idx, p2i(old_tams), p2i(new_tams)); + log_debug(gc)("Capturing TAMS for %s Region %zu, was: " PTR_FORMAT ", now: " PTR_FORMAT, + r->affiliation_name(), idx, p2i(old_tams), p2i(new_tams)); _top_at_mark_starts_base[idx] = new_tams; _top_bitmaps[idx] = new_tams; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahOldGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahOldGC.cpp index 3e9f3a490df9f..1724fc2849f76 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahOldGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahOldGC.cpp @@ -49,7 +49,7 @@ void ShenandoahOldGC::op_final_mark() { assert(!heap->has_forwarded_objects(), "No forwarded objects on this path"); if (ShenandoahVerify) { - heap->verifier()->verify_roots_no_forwarded(_old_generation); + heap->verifier()->verify_roots_no_forwarded(); } if (!heap->cancelled_gc()) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahReferenceProcessor.cpp b/src/hotspot/share/gc/shenandoah/shenandoahReferenceProcessor.cpp index f37329d1c4499..4ca6f2fdf4900 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahReferenceProcessor.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahReferenceProcessor.cpp @@ -329,31 +329,25 @@ bool ShenandoahReferenceProcessor::should_drop(oop reference, ReferenceType type return true; } - shenandoah_assert_mark_complete(raw_referent); ShenandoahHeap* heap = ShenandoahHeap::heap(); - // Check if the referent is still alive, in which case we should drop the reference. + // Check if the referent is still alive, in which case we should + // drop the reference. if (type == REF_PHANTOM) { - return heap->marking_context()->is_marked(raw_referent); + return heap->active_generation()->complete_marking_context()->is_marked(raw_referent); } else { - return heap->marking_context()->is_marked_strong(raw_referent); + return heap->active_generation()->complete_marking_context()->is_marked_strong(raw_referent); } } template void ShenandoahReferenceProcessor::make_inactive(oop reference, ReferenceType type) const { if (type == REF_FINAL) { -#ifdef ASSERT - auto referent = reference_referent_raw(reference); - auto heap = ShenandoahHeap::heap(); - shenandoah_assert_mark_complete(referent); - assert(reference_next(reference) == nullptr, "Already inactive"); - assert(heap->marking_context()->is_marked(referent), "only make inactive final refs with alive referents"); -#endif - // Don't clear referent. It is needed by the Finalizer thread to make the call // to finalize(). A FinalReference is instead made inactive by self-looping the // next field. An application can't call FinalReference.enqueue(), so there is // no race to worry about when setting the next field. + assert(reference_next(reference) == nullptr, "Already inactive"); + assert(ShenandoahHeap::heap()->active_generation()->complete_marking_context()->is_marked(reference_referent_raw(reference)), "only make inactive final refs with alive referents"); reference_set_next(reference, reference); } else { // Clear referent @@ -443,12 +437,8 @@ oop ShenandoahReferenceProcessor::drop(oop reference, ReferenceType type) { HeapWord* raw_referent = reference_referent_raw(reference); #ifdef ASSERT - if (raw_referent != nullptr) { - ShenandoahHeap* heap = ShenandoahHeap::heap(); - ShenandoahHeapRegion* region = heap->heap_region_containing(raw_referent); - ShenandoahMarkingContext* ctx = heap->generation_for(region->affiliation())->complete_marking_context(); - assert(ctx->is_marked(raw_referent), "only drop references with alive referents"); - } + assert(raw_referent == nullptr || ShenandoahHeap::heap()->active_generation()->complete_marking_context()->is_marked(raw_referent), + "only drop references with alive referents"); #endif // Unlink and return next in list diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.cpp index 964b6f0a10ae2..774c4f7d9413e 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.cpp @@ -58,7 +58,6 @@ void ShenandoahRegulatorThread::run_service() { void ShenandoahRegulatorThread::regulate_young_and_old_cycles() { while (!should_terminate()) { - SuspendibleThreadSetJoiner joiner; ShenandoahGenerationalControlThread::GCMode mode = _control_thread->gc_mode(); if (mode == ShenandoahGenerationalControlThread::none) { if (should_start_metaspace_gc()) { @@ -96,7 +95,6 @@ void ShenandoahRegulatorThread::regulate_young_and_old_cycles() { void ShenandoahRegulatorThread::regulate_young_and_global_cycles() { while (!should_terminate()) { - SuspendibleThreadSetJoiner joiner; if (_control_thread->gc_mode() == ShenandoahGenerationalControlThread::none) { if (start_global_cycle()) { log_debug(gc)("Heuristics request for global collection accepted."); @@ -124,7 +122,6 @@ void ShenandoahRegulatorThread::regulator_sleep() { _last_sleep_adjust_time = current; } - SuspendibleThreadSetLeaver leaver; os::naked_short_sleep(_sleep); if (LogTarget(Debug, gc, thread)::is_enabled()) { double elapsed = os::elapsedTime() - current; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp index 9e6b19607089a..a56113868be76 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp @@ -58,9 +58,9 @@ void ShenandoahJavaThreadsIterator::threads_do(ThreadClosure* cl, uint worker_id } ShenandoahThreadRoots::ShenandoahThreadRoots(ShenandoahPhaseTimings::Phase phase, bool is_par) : - _phase(phase), - _is_par(is_par), - _threads_claim_token_scope() {} + _phase(phase), _is_par(is_par) { + Threads::change_thread_claim_token(); +} void ShenandoahThreadRoots::oops_do(OopClosure* oops_cl, NMethodClosure* code_cl, uint worker_id) { ShenandoahWorkerTimingsTracker timer(_phase, ShenandoahPhaseTimings::ThreadRoots, worker_id); @@ -74,6 +74,10 @@ void ShenandoahThreadRoots::threads_do(ThreadClosure* tc, uint worker_id) { Threads::possibly_parallel_threads_do(_is_par, tc); } +ShenandoahThreadRoots::~ShenandoahThreadRoots() { + Threads::assert_all_threads_claimed(); +} + ShenandoahCodeCacheRoots::ShenandoahCodeCacheRoots(ShenandoahPhaseTimings::Phase phase) : _phase(phase) { } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp index 29d8c9fac2d15..40d4077256d04 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp @@ -33,7 +33,6 @@ #include "gc/shenandoah/shenandoahSharedVariables.hpp" #include "gc/shenandoah/shenandoahUtils.hpp" #include "memory/iterator.hpp" -#include "runtime/threads.hpp" template class ShenandoahVMWeakRoots { @@ -88,10 +87,10 @@ class ShenandoahJavaThreadsIterator { class ShenandoahThreadRoots { private: ShenandoahPhaseTimings::Phase _phase; - const bool _is_par; - ThreadsClaimTokenScope _threads_claim_token_scope; + const bool _is_par; public: ShenandoahThreadRoots(ShenandoahPhaseTimings::Phase phase, bool is_par); + ~ShenandoahThreadRoots(); void oops_do(OopClosure* oops_cl, NMethodClosure* code_cl, uint worker_id); void threads_do(ThreadClosure* tc, uint worker_id); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.cpp b/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.cpp index 23edc780e4744..11ff92cd9ccf3 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.cpp @@ -61,7 +61,7 @@ ShenandoahGCStateResetter::~ShenandoahGCStateResetter() { assert(_heap->gc_state() == _saved_gc_state, "Should be restored"); } -void ShenandoahRootVerifier::roots_do(OopIterateClosure* oops, ShenandoahGeneration* generation) { +void ShenandoahRootVerifier::roots_do(OopIterateClosure* oops) { ShenandoahGCStateResetter resetter; shenandoah_assert_safepoint(); @@ -75,9 +75,9 @@ void ShenandoahRootVerifier::roots_do(OopIterateClosure* oops, ShenandoahGenerat OopStorageSet::storage(id)->oops_do(oops); } - if (generation->is_young()) { + ShenandoahHeap* heap = ShenandoahHeap::heap(); + if (heap->mode()->is_generational() && heap->active_generation()->is_young()) { shenandoah_assert_safepoint(); - shenandoah_assert_generational(); ShenandoahGenerationalHeap::heap()->old_generation()->card_scan()->roots_do(oops); } @@ -87,7 +87,7 @@ void ShenandoahRootVerifier::roots_do(OopIterateClosure* oops, ShenandoahGenerat Threads::possibly_parallel_oops_do(true, oops, nullptr); } -void ShenandoahRootVerifier::strong_roots_do(OopIterateClosure* oops, ShenandoahGeneration* generation) { +void ShenandoahRootVerifier::strong_roots_do(OopIterateClosure* oops) { ShenandoahGCStateResetter resetter; shenandoah_assert_safepoint(); @@ -98,8 +98,8 @@ void ShenandoahRootVerifier::strong_roots_do(OopIterateClosure* oops, Shenandoah OopStorageSet::storage(id)->oops_do(oops); } - if (generation->is_young()) { - shenandoah_assert_generational(); + ShenandoahHeap* heap = ShenandoahHeap::heap(); + if (heap->mode()->is_generational() && heap->active_generation()->is_young()) { ShenandoahGenerationalHeap::heap()->old_generation()->card_scan()->roots_do(oops); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.hpp b/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.hpp index 1f3cb40046577..405c69c4160e6 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootVerifier.hpp @@ -43,10 +43,8 @@ class ShenandoahGCStateResetter : public StackObj { class ShenandoahRootVerifier : public AllStatic { public: // Used to seed ShenandoahVerifier, do not honor root type filter - // The generation parameter here may be young or global. If it is young, - // then the roots will include the remembered set. - static void roots_do(OopIterateClosure* cl, ShenandoahGeneration* generation); - static void strong_roots_do(OopIterateClosure* cl, ShenandoahGeneration* generation); + static void roots_do(OopIterateClosure* cl); + static void strong_roots_do(OopIterateClosure* cl); }; #endif // SHARE_GC_SHENANDOAH_SHENANDOAHROOTVERIFIER_HPP diff --git a/src/hotspot/share/gc/shenandoah/shenandoahSTWMark.cpp b/src/hotspot/share/gc/shenandoah/shenandoahSTWMark.cpp index 117984a6d41c5..53391a3e224f3 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahSTWMark.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahSTWMark.cpp @@ -77,13 +77,15 @@ void ShenandoahSTWMark::mark() { ShenandoahCodeRoots::arm_nmethods_for_mark(); // Weak reference processing + assert(ShenandoahHeap::heap()->gc_generation() == _generation, "Marking unexpected generation"); ShenandoahReferenceProcessor* rp = _generation->ref_processor(); + shenandoah_assert_generations_reconciled(); rp->reset_thread_locals(); // Init mark, do not expect forwarded pointers in roots if (ShenandoahVerify) { assert(Thread::current()->is_VM_thread(), "Must be"); - heap->verifier()->verify_roots_no_forwarded(_generation); + heap->verifier()->verify_roots_no_forwarded(); } start_mark(); @@ -117,6 +119,7 @@ void ShenandoahSTWMark::mark() { } void ShenandoahSTWMark::mark_roots(uint worker_id) { + assert(ShenandoahHeap::heap()->gc_generation() == _generation, "Marking unexpected generation"); ShenandoahReferenceProcessor* rp = _generation->ref_processor(); auto queue = task_queues()->queue(worker_id); switch (_generation->type()) { @@ -145,10 +148,14 @@ void ShenandoahSTWMark::mark_roots(uint worker_id) { } void ShenandoahSTWMark::finish_mark(uint worker_id) { + assert(ShenandoahHeap::heap()->gc_generation() == _generation, "Marking unexpected generation"); ShenandoahPhaseTimings::Phase phase = _full_gc ? ShenandoahPhaseTimings::full_gc_mark : ShenandoahPhaseTimings::degen_gc_stw_mark; ShenandoahWorkerTimingsTracker timer(phase, ShenandoahPhaseTimings::ParallelMark, worker_id); + ShenandoahReferenceProcessor* rp = _generation->ref_processor(); + shenandoah_assert_generations_reconciled(); StringDedup::Requests requests; - mark_loop(worker_id, &_terminator, _generation->type(), false /* not cancellable */, + mark_loop(worker_id, &_terminator, rp, + _generation->type(), false /* not cancellable */, ShenandoahStringDedup::is_enabled() ? ALWAYS_DEDUP : NO_DEDUP, &requests); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.cpp b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.cpp index 4a0215f15f199..23c705348c409 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.cpp @@ -683,9 +683,9 @@ void ShenandoahScanRememberedTask::do_work(uint worker_id) { struct ShenandoahRegionChunk assignment; while (_work_list->next(&assignment)) { ShenandoahHeapRegion* region = assignment._r; - log_debug(gc, remset)("ShenandoahScanRememberedTask::do_work(%u), processing slice of region " - "%zu at offset %zu, size: %zu", - worker_id, region->index(), assignment._chunk_offset, assignment._chunk_size); + log_debug(gc)("ShenandoahScanRememberedTask::do_work(%u), processing slice of region " + "%zu at offset %zu, size: %zu", + worker_id, region->index(), assignment._chunk_offset, assignment._chunk_size); if (region->is_old()) { size_t cluster_size = CardTable::card_size_in_words() * ShenandoahCardCluster::CardsPerCluster; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.inline.hpp index 919cc4f6fd796..ce7cda984121a 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.inline.hpp @@ -343,9 +343,9 @@ ShenandoahScanRemembered::process_region_slice(ShenandoahHeapRegion *region, siz } } - log_debug(gc, remset)("Remembered set scan processing Region %zu, from " PTR_FORMAT " to " PTR_FORMAT ", using %s table", - region->index(), p2i(start_of_range), p2i(end_of_range), - use_write_table? "read/write (updating)": "read (marking)"); + log_debug(gc)("Remembered set scan processing Region %zu, from " PTR_FORMAT " to " PTR_FORMAT ", using %s table", + region->index(), p2i(start_of_range), p2i(end_of_range), + use_write_table? "read/write (updating)": "read (marking)"); // Note that end_of_range may point to the middle of a cluster because we limit scanning to // region->top() or region->get_update_watermark(). We avoid processing past end_of_range. diff --git a/src/hotspot/share/gc/shenandoah/shenandoahVMOperations.cpp b/src/hotspot/share/gc/shenandoah/shenandoahVMOperations.cpp index 6b45842f78174..0137492f06f81 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahVMOperations.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahVMOperations.cpp @@ -50,14 +50,16 @@ void VM_ShenandoahOperation::doit_epilogue() { void VM_ShenandoahOperation::log_active_generation(const char* prefix) { ShenandoahGeneration* agen = ShenandoahHeap::heap()->active_generation(); - log_debug(gc, heap)("%s: active_generation is %s", prefix, - agen == nullptr ? "nullptr" : shenandoah_generation_name(agen->type())); + ShenandoahGeneration* ggen = ShenandoahHeap::heap()->gc_generation(); + log_debug(gc, heap)("%s: active_generation is %s, gc_generation is %s", prefix, + agen == nullptr ? "nullptr" : shenandoah_generation_name(agen->type()), + ggen == nullptr ? "nullptr" : shenandoah_generation_name(ggen->type())); } void VM_ShenandoahOperation::set_active_generation() { if (evaluate_at_safepoint()) { assert(SafepointSynchronize::is_at_safepoint(), "Error??"); - ShenandoahHeap::heap()->set_active_generation(_generation); + ShenandoahHeap::heap()->set_active_generation(); } } @@ -75,70 +77,42 @@ void VM_ShenandoahReferenceOperation::doit_epilogue() { Heap_lock->unlock(); } -VM_ShenandoahInitMark::VM_ShenandoahInitMark(ShenandoahConcurrentGC* gc) - : VM_ShenandoahOperation(gc->generation()), _gc(gc) { -} - void VM_ShenandoahInitMark::doit() { ShenandoahGCPauseMark mark(_gc_id, "Init Mark", SvcGCMarker::CONCURRENT); set_active_generation(); _gc->entry_init_mark(); } -VM_ShenandoahFinalMarkStartEvac::VM_ShenandoahFinalMarkStartEvac(ShenandoahConcurrentGC* gc) - : VM_ShenandoahOperation(gc->generation()), _gc(gc) { -} - void VM_ShenandoahFinalMarkStartEvac::doit() { ShenandoahGCPauseMark mark(_gc_id, "Final Mark", SvcGCMarker::CONCURRENT); set_active_generation(); _gc->entry_final_mark(); } -VM_ShenandoahFullGC::VM_ShenandoahFullGC(GCCause::Cause gc_cause, ShenandoahFullGC* full_gc) - : VM_ShenandoahReferenceOperation(full_gc->generation()), _gc_cause(gc_cause), _full_gc(full_gc) { -} - void VM_ShenandoahFullGC::doit() { ShenandoahGCPauseMark mark(_gc_id, "Full GC", SvcGCMarker::FULL); set_active_generation(); _full_gc->entry_full(_gc_cause); } -VM_ShenandoahDegeneratedGC::VM_ShenandoahDegeneratedGC(ShenandoahDegenGC* gc) - : VM_ShenandoahReferenceOperation(gc->generation()), _gc(gc) { -} - void VM_ShenandoahDegeneratedGC::doit() { ShenandoahGCPauseMark mark(_gc_id, "Degenerated GC", SvcGCMarker::CONCURRENT); set_active_generation(); _gc->entry_degenerated(); } -VM_ShenandoahInitUpdateRefs::VM_ShenandoahInitUpdateRefs(ShenandoahConcurrentGC* gc) - : VM_ShenandoahOperation(gc->generation()), _gc(gc) { -} - void VM_ShenandoahInitUpdateRefs::doit() { ShenandoahGCPauseMark mark(_gc_id, "Init Update Refs", SvcGCMarker::CONCURRENT); set_active_generation(); _gc->entry_init_update_refs(); } -VM_ShenandoahFinalUpdateRefs::VM_ShenandoahFinalUpdateRefs(ShenandoahConcurrentGC* gc) - : VM_ShenandoahOperation(gc->generation()), _gc(gc) { -} - void VM_ShenandoahFinalUpdateRefs::doit() { ShenandoahGCPauseMark mark(_gc_id, "Final Update Refs", SvcGCMarker::CONCURRENT); set_active_generation(); _gc->entry_final_update_refs(); } -VM_ShenandoahFinalRoots::VM_ShenandoahFinalRoots(ShenandoahConcurrentGC* gc) - : VM_ShenandoahOperation(gc->generation()), _gc(gc) { -} - void VM_ShenandoahFinalRoots::doit() { ShenandoahGCPauseMark mark(_gc_id, "Final Roots", SvcGCMarker::CONCURRENT); set_active_generation(); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahVMOperations.hpp b/src/hotspot/share/gc/shenandoah/shenandoahVMOperations.hpp index d565a3df22c96..291fadd18874e 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahVMOperations.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahVMOperations.hpp @@ -46,15 +46,10 @@ class ShenandoahFullGC; class VM_ShenandoahOperation : public VM_Operation { protected: uint _gc_id; - ShenandoahGeneration* _generation; void set_active_generation(); public: - explicit VM_ShenandoahOperation(ShenandoahGeneration* generation) - : _gc_id(GCId::current()) - , _generation(generation) { - } - + VM_ShenandoahOperation() : _gc_id(GCId::current()) {}; bool skip_thread_oop_barriers() const override { return true; } void log_active_generation(const char* prefix); @@ -66,74 +61,93 @@ class VM_ShenandoahOperation : public VM_Operation { class VM_ShenandoahReferenceOperation : public VM_ShenandoahOperation { public: - explicit VM_ShenandoahReferenceOperation(ShenandoahGeneration* generation) - : VM_ShenandoahOperation(generation) {}; + VM_ShenandoahReferenceOperation() : VM_ShenandoahOperation() {}; bool doit_prologue() override; void doit_epilogue() override; }; class VM_ShenandoahInitMark: public VM_ShenandoahOperation { +private: ShenandoahConcurrentGC* const _gc; public: - explicit VM_ShenandoahInitMark(ShenandoahConcurrentGC* gc); - VM_Operation::VMOp_Type type() const override { return VMOp_ShenandoahInitMark; } - const char* name() const override { return "Shenandoah Init Marking"; } - void doit() override; + VM_ShenandoahInitMark(ShenandoahConcurrentGC* gc) : + VM_ShenandoahOperation(), + _gc(gc) {}; + VM_Operation::VMOp_Type type() const { return VMOp_ShenandoahInitMark; } + const char* name() const { return "Shenandoah Init Marking"; } + virtual void doit(); }; class VM_ShenandoahFinalMarkStartEvac: public VM_ShenandoahOperation { +private: ShenandoahConcurrentGC* const _gc; public: - explicit VM_ShenandoahFinalMarkStartEvac(ShenandoahConcurrentGC* gc); - VM_Operation::VMOp_Type type() const override { return VMOp_ShenandoahFinalMarkStartEvac; } - const char* name() const override { return "Shenandoah Final Mark and Start Evacuation"; } - void doit() override; + VM_ShenandoahFinalMarkStartEvac(ShenandoahConcurrentGC* gc) : + VM_ShenandoahOperation(), + _gc(gc) {}; + VM_Operation::VMOp_Type type() const { return VMOp_ShenandoahFinalMarkStartEvac; } + const char* name() const { return "Shenandoah Final Mark and Start Evacuation"; } + virtual void doit(); }; class VM_ShenandoahDegeneratedGC: public VM_ShenandoahReferenceOperation { +private: ShenandoahDegenGC* const _gc; public: - explicit VM_ShenandoahDegeneratedGC(ShenandoahDegenGC* gc); - VM_Operation::VMOp_Type type() const override { return VMOp_ShenandoahDegeneratedGC; } - const char* name() const override { return "Shenandoah Degenerated GC"; } - void doit() override; + VM_ShenandoahDegeneratedGC(ShenandoahDegenGC* gc) : + VM_ShenandoahReferenceOperation(), + _gc(gc) {}; + + VM_Operation::VMOp_Type type() const { return VMOp_ShenandoahDegeneratedGC; } + const char* name() const { return "Shenandoah Degenerated GC"; } + virtual void doit(); }; class VM_ShenandoahFullGC : public VM_ShenandoahReferenceOperation { +private: GCCause::Cause _gc_cause; ShenandoahFullGC* const _full_gc; public: - explicit VM_ShenandoahFullGC(GCCause::Cause gc_cause, ShenandoahFullGC* full_gc); - VM_Operation::VMOp_Type type() const override { return VMOp_ShenandoahFullGC; } - const char* name() const override { return "Shenandoah Full GC"; } - void doit() override; + VM_ShenandoahFullGC(GCCause::Cause gc_cause, ShenandoahFullGC* full_gc) : + VM_ShenandoahReferenceOperation(), + _gc_cause(gc_cause), + _full_gc(full_gc) {}; + VM_Operation::VMOp_Type type() const { return VMOp_ShenandoahFullGC; } + const char* name() const { return "Shenandoah Full GC"; } + virtual void doit(); }; class VM_ShenandoahInitUpdateRefs: public VM_ShenandoahOperation { ShenandoahConcurrentGC* const _gc; public: - explicit VM_ShenandoahInitUpdateRefs(ShenandoahConcurrentGC* gc); - VM_Operation::VMOp_Type type() const override { return VMOp_ShenandoahInitUpdateRefs; } - const char* name() const override { return "Shenandoah Init Update References"; } - void doit() override; + VM_ShenandoahInitUpdateRefs(ShenandoahConcurrentGC* gc) : + VM_ShenandoahOperation(), + _gc(gc) {}; + VM_Operation::VMOp_Type type() const { return VMOp_ShenandoahInitUpdateRefs; } + const char* name() const { return "Shenandoah Init Update References"; } + virtual void doit(); }; class VM_ShenandoahFinalUpdateRefs: public VM_ShenandoahOperation { ShenandoahConcurrentGC* const _gc; public: - explicit VM_ShenandoahFinalUpdateRefs(ShenandoahConcurrentGC* gc); - VM_Operation::VMOp_Type type() const override { return VMOp_ShenandoahFinalUpdateRefs; } - const char* name() const override { return "Shenandoah Final Update References"; } - void doit() override; + VM_ShenandoahFinalUpdateRefs(ShenandoahConcurrentGC* gc) : + VM_ShenandoahOperation(), + _gc(gc) {}; + VM_Operation::VMOp_Type type() const { return VMOp_ShenandoahFinalUpdateRefs; } + const char* name() const { return "Shenandoah Final Update References"; } + virtual void doit(); }; class VM_ShenandoahFinalRoots: public VM_ShenandoahOperation { ShenandoahConcurrentGC* const _gc; public: - explicit VM_ShenandoahFinalRoots(ShenandoahConcurrentGC* gc); - VM_Operation::VMOp_Type type() const override { return VMOp_ShenandoahFinalRoots; } - const char* name() const override { return "Shenandoah Final Roots"; } - void doit() override; + VM_ShenandoahFinalRoots(ShenandoahConcurrentGC* gc) : + VM_ShenandoahOperation(), + _gc(gc) {}; + VM_Operation::VMOp_Type type() const { return VMOp_ShenandoahFinalRoots; } + const char* name() const { return "Shenandoah Final Roots"; } + virtual void doit(); }; #endif // SHARE_GC_SHENANDOAH_SHENANDOAHVMOPERATIONS_HPP diff --git a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp index fb5fbbd00a152..c84a2a656771b 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.cpp @@ -70,8 +70,7 @@ class ShenandoahVerifyOopClosure : public BasicOopIterateClosure { ShenandoahGeneration* _generation; public: - ShenandoahVerifyOopClosure(ShenandoahGeneration* generation, ShenandoahVerifierStack* stack, - MarkBitMap* map, ShenandoahLivenessData* ld, + ShenandoahVerifyOopClosure(ShenandoahVerifierStack* stack, MarkBitMap* map, ShenandoahLivenessData* ld, const char* phase, ShenandoahVerifier::VerifyOptions options) : _phase(phase), _options(options), @@ -81,7 +80,7 @@ class ShenandoahVerifyOopClosure : public BasicOopIterateClosure { _ld(ld), _interior_loc(nullptr), _loc(nullptr), - _generation(generation) { + _generation(nullptr) { if (options._verify_marked == ShenandoahVerifier::_verify_marked_complete_except_references || options._verify_marked == ShenandoahVerifier::_verify_marked_complete_satb_empty || options._verify_marked == ShenandoahVerifier::_verify_marked_disable) { @@ -93,6 +92,12 @@ class ShenandoahVerifyOopClosure : public BasicOopIterateClosure { // Otherwise do all fields. _ref_mode = DO_FIELDS; } + + if (_heap->mode()->is_generational()) { + _generation = _heap->gc_generation(); + assert(_generation != nullptr, "Expected active generation in this mode"); + shenandoah_assert_generations_reconciled(); + } } ReferenceIterationMode reference_iteration_mode() override { @@ -126,7 +131,11 @@ class ShenandoahVerifyOopClosure : public BasicOopIterateClosure { } } - bool in_generation(oop obj) const { + bool in_generation(oop obj) { + if (_generation == nullptr) { + return true; + } + ShenandoahHeapRegion* region = _heap->heap_region_containing(obj); return _generation->contains(region); } @@ -188,8 +197,9 @@ class ShenandoahVerifyOopClosure : public BasicOopIterateClosure { // fallthrough for fast failure for un-live regions: case ShenandoahVerifier::_verify_liveness_conservative: check(ShenandoahAsserts::_safe_oop, obj, obj_reg->has_live() || - (obj_reg->is_old() && _generation->is_young()), + (obj_reg->is_old() && _heap->gc_generation()->is_young()), "Object must belong to region with live data"); + shenandoah_assert_generations_reconciled(); break; default: assert(false, "Unhandled liveness verification"); @@ -266,12 +276,12 @@ class ShenandoahVerifyOopClosure : public BasicOopIterateClosure { "Must be marked in incomplete bitmap"); break; case ShenandoahVerifier::_verify_marked_complete: - check(ShenandoahAsserts::_safe_all, obj, _generation->complete_marking_context()->is_marked(obj), + check(ShenandoahAsserts::_safe_all, obj, _heap->gc_generation()->complete_marking_context()->is_marked(obj), "Must be marked in complete bitmap"); break; case ShenandoahVerifier::_verify_marked_complete_except_references: case ShenandoahVerifier::_verify_marked_complete_satb_empty: - check(ShenandoahAsserts::_safe_all, obj, _generation->complete_marking_context()->is_marked(obj), + check(ShenandoahAsserts::_safe_all, obj, _heap->gc_generation()->complete_marking_context()->is_marked(obj), "Must be marked in complete bitmap, except j.l.r.Reference referents"); break; default: @@ -561,11 +571,9 @@ class ShenandoahVerifierReachableTask : public WorkerTask { ShenandoahLivenessData* _ld; MarkBitMap* _bitmap; volatile size_t _processed; - ShenandoahGeneration* _generation; public: - ShenandoahVerifierReachableTask(ShenandoahGeneration* generation, - MarkBitMap* bitmap, + ShenandoahVerifierReachableTask(MarkBitMap* bitmap, ShenandoahLivenessData* ld, const char* label, ShenandoahVerifier::VerifyOptions options) : @@ -575,8 +583,7 @@ class ShenandoahVerifierReachableTask : public WorkerTask { _heap(ShenandoahHeap::heap()), _ld(ld), _bitmap(bitmap), - _processed(0), - _generation(generation) {}; + _processed(0) {}; size_t processed() const { return _processed; @@ -592,20 +599,20 @@ class ShenandoahVerifierReachableTask : public WorkerTask { // extended parallelism would buy us out. if (((ShenandoahVerifyLevel == 2) && (worker_id == 0)) || (ShenandoahVerifyLevel >= 3)) { - ShenandoahVerifyOopClosure cl(_generation, &stack, _bitmap, _ld, + ShenandoahVerifyOopClosure cl(&stack, _bitmap, _ld, ShenandoahMessageBuffer("%s, Roots", _label), _options); if (_heap->unload_classes()) { - ShenandoahRootVerifier::strong_roots_do(&cl, _generation); + ShenandoahRootVerifier::strong_roots_do(&cl); } else { - ShenandoahRootVerifier::roots_do(&cl, _generation); + ShenandoahRootVerifier::roots_do(&cl); } } size_t processed = 0; if (ShenandoahVerifyLevel >= 3) { - ShenandoahVerifyOopClosure cl(_generation, &stack, _bitmap, _ld, + ShenandoahVerifyOopClosure cl(&stack, _bitmap, _ld, ShenandoahMessageBuffer("%s, Reachable", _label), _options); while (!stack.is_empty()) { @@ -641,8 +648,7 @@ class ShenandoahVerifierMarkedRegionTask : public WorkerTask { ShenandoahGeneration* _generation; public: - ShenandoahVerifierMarkedRegionTask(ShenandoahGeneration* generation, - MarkBitMap* bitmap, + ShenandoahVerifierMarkedRegionTask(MarkBitMap* bitmap, ShenandoahLivenessData* ld, const char* label, ShenandoahVerifier::VerifyOptions options) : @@ -654,7 +660,13 @@ class ShenandoahVerifierMarkedRegionTask : public WorkerTask { _ld(ld), _claimed(0), _processed(0), - _generation(generation) {} + _generation(nullptr) { + if (_heap->mode()->is_generational()) { + _generation = _heap->gc_generation(); + assert(_generation != nullptr, "Expected active generation in this mode."); + shenandoah_assert_generations_reconciled(); + } + }; size_t processed() { return AtomicAccess::load(&_processed); @@ -667,7 +679,7 @@ class ShenandoahVerifierMarkedRegionTask : public WorkerTask { } ShenandoahVerifierStack stack; - ShenandoahVerifyOopClosure cl(_generation, &stack, _bitmap, _ld, + ShenandoahVerifyOopClosure cl(&stack, _bitmap, _ld, ShenandoahMessageBuffer("%s, Marked", _label), _options); @@ -690,14 +702,14 @@ class ShenandoahVerifierMarkedRegionTask : public WorkerTask { } } - bool in_generation(ShenandoahHeapRegion* r) const { - return _generation->contains(r); + bool in_generation(ShenandoahHeapRegion* r) { + return _generation == nullptr || _generation->contains(r); } virtual void work_humongous(ShenandoahHeapRegion *r, ShenandoahVerifierStack& stack, ShenandoahVerifyOopClosure& cl) { size_t processed = 0; HeapWord* obj = r->bottom(); - if (_generation->complete_marking_context()->is_marked(cast_to_oop(obj))) { + if (_heap->gc_generation()->complete_marking_context()->is_marked(cast_to_oop(obj))) { verify_and_follow(obj, stack, cl, &processed); } AtomicAccess::add(&_processed, processed, memory_order_relaxed); @@ -705,7 +717,7 @@ class ShenandoahVerifierMarkedRegionTask : public WorkerTask { virtual void work_regular(ShenandoahHeapRegion *r, ShenandoahVerifierStack &stack, ShenandoahVerifyOopClosure &cl) { size_t processed = 0; - ShenandoahMarkingContext* ctx = _generation->complete_marking_context(); + ShenandoahMarkingContext* ctx = _heap->gc_generation()->complete_marking_context(); HeapWord* tams = ctx->top_at_mark_start(r); // Bitmaps, before TAMS @@ -782,8 +794,7 @@ class VerifyThreadGCState : public ThreadClosure { } }; -void ShenandoahVerifier::verify_at_safepoint(ShenandoahGeneration* generation, - const char* label, +void ShenandoahVerifier::verify_at_safepoint(const char* label, VerifyRememberedSet remembered, VerifyForwarded forwarded, VerifyMarked marked, @@ -885,7 +896,16 @@ void ShenandoahVerifier::verify_at_safepoint(ShenandoahGeneration* generation, log_debug(gc)("Safepoint verification finished heap usage verification"); + ShenandoahGeneration* generation; if (_heap->mode()->is_generational()) { + generation = _heap->gc_generation(); + guarantee(generation != nullptr, "Need to know which generation to verify."); + shenandoah_assert_generations_reconciled(); + } else { + generation = nullptr; + } + + if (generation != nullptr) { ShenandoahHeapLocker lock(_heap->lock()); switch (remembered) { @@ -932,7 +952,11 @@ void ShenandoahVerifier::verify_at_safepoint(ShenandoahGeneration* generation, // Internal heap region checks if (ShenandoahVerifyLevel >= 1) { ShenandoahVerifyHeapRegionClosure cl(label, regions); - generation->heap_region_iterate(&cl); + if (generation != nullptr) { + generation->heap_region_iterate(&cl); + } else { + _heap->heap_region_iterate(&cl); + } } log_debug(gc)("Safepoint verification finished heap region closure verification"); @@ -956,7 +980,7 @@ void ShenandoahVerifier::verify_at_safepoint(ShenandoahGeneration* generation, // This verifies what application can see, since it only cares about reachable objects. size_t count_reachable = 0; if (ShenandoahVerifyLevel >= 2) { - ShenandoahVerifierReachableTask task(generation, _verification_bit_map, ld, label, options); + ShenandoahVerifierReachableTask task(_verification_bit_map, ld, label, options); _heap->workers()->run_task(&task); count_reachable = task.processed(); } @@ -975,8 +999,8 @@ void ShenandoahVerifier::verify_at_safepoint(ShenandoahGeneration* generation, (marked == _verify_marked_complete || marked == _verify_marked_complete_except_references || marked == _verify_marked_complete_satb_empty)) { - guarantee(generation->is_mark_complete(), "Marking context should be complete"); - ShenandoahVerifierMarkedRegionTask task(generation, _verification_bit_map, ld, label, options); + guarantee(_heap->gc_generation()->is_mark_complete(), "Marking context should be complete"); + ShenandoahVerifierMarkedRegionTask task(_verification_bit_map, ld, label, options); _heap->workers()->run_task(&task); count_marked = task.processed(); } else { @@ -991,7 +1015,7 @@ void ShenandoahVerifier::verify_at_safepoint(ShenandoahGeneration* generation, if (ShenandoahVerifyLevel >= 4 && marked == _verify_marked_complete && liveness == _verify_liveness_complete) { for (size_t i = 0; i < _heap->num_regions(); i++) { ShenandoahHeapRegion* r = _heap->get_region(i); - if (!generation->contains(r)) { + if (generation != nullptr && !generation->contains(r)) { continue; } @@ -1018,15 +1042,16 @@ void ShenandoahVerifier::verify_at_safepoint(ShenandoahGeneration* generation, } log_debug(gc)("Safepoint verification finished accumulation of liveness data"); + + log_info(gc)("Verify %s, Level %zd (%zu reachable, %zu marked)", label, ShenandoahVerifyLevel, count_reachable, count_marked); FREE_C_HEAP_ARRAY(ShenandoahLivenessData, ld); } -void ShenandoahVerifier::verify_generic(ShenandoahGeneration* generation, VerifyOption vo) { +void ShenandoahVerifier::verify_generic(VerifyOption vo) { verify_at_safepoint( - generation, "Generic Verification", _verify_remembered_disable, // do not verify remembered set _verify_forwarded_allow, // conservatively allow forwarded @@ -1039,7 +1064,7 @@ void ShenandoahVerifier::verify_generic(ShenandoahGeneration* generation, Verify ); } -void ShenandoahVerifier::verify_before_concmark(ShenandoahGeneration* generation) { +void ShenandoahVerifier::verify_before_concmark() { VerifyRememberedSet verify_remembered_set = _verify_remembered_before_marking; if (_heap->mode()->is_generational() && !_heap->old_generation()->is_mark_complete()) { @@ -1047,7 +1072,6 @@ void ShenandoahVerifier::verify_before_concmark(ShenandoahGeneration* generation verify_remembered_set = _verify_remembered_disable; } verify_at_safepoint( - generation, "Before Mark", verify_remembered_set, // verify read-only remembered set from bottom() to top() @@ -1061,9 +1085,8 @@ void ShenandoahVerifier::verify_before_concmark(ShenandoahGeneration* generation ); } -void ShenandoahVerifier::verify_after_concmark(ShenandoahGeneration* generation) { +void ShenandoahVerifier::verify_after_concmark() { verify_at_safepoint( - generation, "After Mark", _verify_remembered_disable, // do not verify remembered set _verify_forwarded_none, // no forwarded references @@ -1076,9 +1099,8 @@ void ShenandoahVerifier::verify_after_concmark(ShenandoahGeneration* generation) ); } -void ShenandoahVerifier::verify_after_concmark_with_promotions(ShenandoahGeneration* generation) { +void ShenandoahVerifier::verify_after_concmark_with_promotions() { verify_at_safepoint( - generation, "After Mark", _verify_remembered_disable, // do not verify remembered set _verify_forwarded_none, // no forwarded references @@ -1092,9 +1114,8 @@ void ShenandoahVerifier::verify_after_concmark_with_promotions(ShenandoahGenerat ); } -void ShenandoahVerifier::verify_before_evacuation(ShenandoahGeneration* generation) { +void ShenandoahVerifier::verify_before_evacuation() { verify_at_safepoint( - generation, "Before Evacuation", _verify_remembered_disable, // do not verify remembered set _verify_forwarded_none, // no forwarded references @@ -1108,14 +1129,13 @@ void ShenandoahVerifier::verify_before_evacuation(ShenandoahGeneration* generati ); } -void ShenandoahVerifier::verify_before_update_refs(ShenandoahGeneration* generation) { +void ShenandoahVerifier::verify_before_update_refs() { VerifyRememberedSet verify_remembered_set = _verify_remembered_before_updating_references; if (_heap->mode()->is_generational() && !_heap->old_generation()->is_mark_complete()) { verify_remembered_set = _verify_remembered_disable; } verify_at_safepoint( - generation, "Before Updating References", verify_remembered_set, // verify read-write remembered set _verify_forwarded_allow, // forwarded references allowed @@ -1129,9 +1149,8 @@ void ShenandoahVerifier::verify_before_update_refs(ShenandoahGeneration* generat } // We have not yet cleanup (reclaimed) the collection set -void ShenandoahVerifier::verify_after_update_refs(ShenandoahGeneration* generation) { +void ShenandoahVerifier::verify_after_update_refs() { verify_at_safepoint( - generation, "After Updating References", _verify_remembered_disable, // do not verify remembered set _verify_forwarded_none, // no forwarded references @@ -1144,9 +1163,8 @@ void ShenandoahVerifier::verify_after_update_refs(ShenandoahGeneration* generati ); } -void ShenandoahVerifier::verify_after_degenerated(ShenandoahGeneration* generation) { +void ShenandoahVerifier::verify_after_degenerated() { verify_at_safepoint( - generation, "After Degenerated GC", _verify_remembered_disable, // do not verify remembered set _verify_forwarded_none, // all objects are non-forwarded @@ -1159,9 +1177,8 @@ void ShenandoahVerifier::verify_after_degenerated(ShenandoahGeneration* generati ); } -void ShenandoahVerifier::verify_before_fullgc(ShenandoahGeneration* generation) { +void ShenandoahVerifier::verify_before_fullgc() { verify_at_safepoint( - generation, "Before Full GC", _verify_remembered_disable, // do not verify remembered set _verify_forwarded_allow, // can have forwarded objects @@ -1174,9 +1191,8 @@ void ShenandoahVerifier::verify_before_fullgc(ShenandoahGeneration* generation) ); } -void ShenandoahVerifier::verify_after_fullgc(ShenandoahGeneration* generation) { +void ShenandoahVerifier::verify_after_fullgc() { verify_at_safepoint( - generation, "After Full GC", _verify_remembered_after_full_gc, // verify read-write remembered set _verify_forwarded_none, // all objects are non-forwarded @@ -1241,14 +1257,14 @@ class ShenandoahVerifyInToSpaceClosure : public BasicOopIterateClosure { void do_oop(oop* p) override { do_oop_work(p); } }; -void ShenandoahVerifier::verify_roots_in_to_space(ShenandoahGeneration* generation) { +void ShenandoahVerifier::verify_roots_in_to_space() { ShenandoahVerifyInToSpaceClosure cl; - ShenandoahRootVerifier::roots_do(&cl, generation); + ShenandoahRootVerifier::roots_do(&cl); } -void ShenandoahVerifier::verify_roots_no_forwarded(ShenandoahGeneration* generation) { +void ShenandoahVerifier::verify_roots_no_forwarded() { ShenandoahVerifyNoForwarded cl; - ShenandoahRootVerifier::roots_do(&cl, generation); + ShenandoahRootVerifier::roots_do(&cl); } template @@ -1284,6 +1300,7 @@ class ShenandoahVerifyRemSetClosure : public BasicOopIterateClosure { template void ShenandoahVerifier::help_verify_region_rem_set(Scanner* scanner, ShenandoahHeapRegion* r, HeapWord* registration_watermark, const char* message) { + shenandoah_assert_generations_reconciled(); ShenandoahOldGeneration* old_gen = _heap->old_generation(); assert(old_gen->is_mark_complete() || old_gen->is_parsable(), "Sanity"); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.hpp b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.hpp index e49990fdc620d..aba6379e0223c 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahVerifier.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahVerifier.hpp @@ -196,8 +196,7 @@ class ShenandoahVerifier : public CHeapObj { }; private: - void verify_at_safepoint(ShenandoahGeneration* generation, - const char* label, + void verify_at_safepoint(const char* label, VerifyRememberedSet remembered, VerifyForwarded forwarded, VerifyMarked marked, @@ -211,20 +210,20 @@ class ShenandoahVerifier : public CHeapObj { ShenandoahVerifier(ShenandoahHeap* heap, MarkBitMap* verification_bitmap) : _heap(heap), _verification_bit_map(verification_bitmap) {}; - void verify_before_concmark(ShenandoahGeneration* generation); - void verify_after_concmark(ShenandoahGeneration* generation); - void verify_after_concmark_with_promotions(ShenandoahGeneration* generation); - void verify_before_evacuation(ShenandoahGeneration* generation); - void verify_before_update_refs(ShenandoahGeneration* generation); - void verify_after_update_refs(ShenandoahGeneration* generation); - void verify_before_fullgc(ShenandoahGeneration* generation); - void verify_after_fullgc(ShenandoahGeneration* generation); - void verify_after_degenerated(ShenandoahGeneration* generation); - void verify_generic(ShenandoahGeneration* generation, VerifyOption option); + void verify_before_concmark(); + void verify_after_concmark(); + void verify_after_concmark_with_promotions(); + void verify_before_evacuation(); + void verify_before_update_refs(); + void verify_after_update_refs(); + void verify_before_fullgc(); + void verify_after_fullgc(); + void verify_after_degenerated(); + void verify_generic(VerifyOption option); // Roots should only contain to-space oops - void verify_roots_in_to_space(ShenandoahGeneration* generation); - void verify_roots_no_forwarded(ShenandoahGeneration* generation); + void verify_roots_in_to_space(); + void verify_roots_no_forwarded(); // Check that generation usages are accurate before rebuilding free set void verify_before_rebuilding_free_set(); diff --git a/src/hotspot/share/gc/z/zNUMA.hpp b/src/hotspot/share/gc/z/zNUMA.hpp index 838a114c210ef..de74086b10ab0 100644 --- a/src/hotspot/share/gc/z/zNUMA.hpp +++ b/src/hotspot/share/gc/z/zNUMA.hpp @@ -53,8 +53,6 @@ class ZNUMA : public AllStatic { static size_t calculate_share(uint32_t numa_id, size_t total, size_t granule = ZGranuleSize, uint32_t ignore_count = 0); static const char* to_string(); - - static int numa_id_to_node(uint32_t numa_id); }; #endif // SHARE_GC_Z_ZNUMA_HPP diff --git a/src/hotspot/share/gc/z/zPhysicalMemoryManager.cpp b/src/hotspot/share/gc/z/zPhysicalMemoryManager.cpp index 2e7a97028ff31..1a38efb89fd5b 100644 --- a/src/hotspot/share/gc/z/zPhysicalMemoryManager.cpp +++ b/src/hotspot/share/gc/z/zPhysicalMemoryManager.cpp @@ -108,7 +108,7 @@ void ZPhysicalMemoryManager::try_enable_uncommit(size_t min_capacity, size_t max // Test if uncommit is supported by the operating system by committing // and then uncommitting a granule. const ZVirtualMemory vmem(zoffset(0), ZGranuleSize); - if (!commit(vmem, 0) || !uncommit(vmem)) { + if (!commit(vmem, (uint32_t)-1) || !uncommit(vmem)) { log_info_p(gc, init)("Uncommit: Implicitly Disabled (Not supported by operating system)"); FLAG_SET_ERGO(ZUncommit, false); return; @@ -293,7 +293,7 @@ void ZPhysicalMemoryManager::map(const ZVirtualMemory& vmem, uint32_t numa_id) c // Setup NUMA preferred for large pages if (ZNUMA::is_enabled() && ZLargePages::is_explicit()) { - os::numa_make_local((char*)addr, size, ZNUMA::numa_id_to_node(numa_id)); + os::numa_make_local((char*)addr, size, (int)numa_id); } } diff --git a/src/hotspot/share/interpreter/abstractInterpreter.cpp b/src/hotspot/share/interpreter/abstractInterpreter.cpp index b6a2255b4686c..640e3ab3fff93 100644 --- a/src/hotspot/share/interpreter/abstractInterpreter.cpp +++ b/src/hotspot/share/interpreter/abstractInterpreter.cpp @@ -258,8 +258,7 @@ bool AbstractInterpreter::is_not_reached(const methodHandle& method, int bci) { case Bytecodes::_invokedynamic: { assert(invoke_bc.has_index_u4(code), "sanity"); int method_index = invoke_bc.get_index_u4(code); - bool is_resolved = cpool->resolved_indy_entry_at(method_index)->is_resolved(); - return !is_resolved; + return cpool->resolved_indy_entry_at(method_index)->is_resolved(); } case Bytecodes::_invokevirtual: // fall-through case Bytecodes::_invokeinterface: // fall-through diff --git a/src/hotspot/share/interpreter/bytecodeStream.hpp b/src/hotspot/share/interpreter/bytecodeStream.hpp index 412951691c536..89d97053b45e2 100644 --- a/src/hotspot/share/interpreter/bytecodeStream.hpp +++ b/src/hotspot/share/interpreter/bytecodeStream.hpp @@ -100,23 +100,8 @@ class BaseBytecodeStream: StackObj { void set_next_bci(int bci) { assert(0 <= bci && bci <= method()->code_size(), "illegal bci"); _next_bci = bci; } // Bytecode-specific attributes - int get_offset_s2() const { return bytecode().get_offset_s2(raw_code()); } - int get_offset_s4() const { return bytecode().get_offset_s4(raw_code()); } - - // These methods are not safe to use before or during verification as they may - // have large offsets and cause overflows - int dest() const { - int min_offset = -1 * max_method_code_size; - int offset = bytecode().get_offset_s2(raw_code()); - guarantee(offset >= min_offset && offset <= max_method_code_size, "must be"); - return bci() + offset; - } - int dest_w() const { - int min_offset = -1 * max_method_code_size; - int offset = bytecode().get_offset_s4(raw_code()); - guarantee(offset >= min_offset && offset <= max_method_code_size, "must be"); - return bci() + offset; - } + int dest() const { return bci() + bytecode().get_offset_s2(raw_code()); } + int dest_w() const { return bci() + bytecode().get_offset_s4(raw_code()); } // One-byte indices. u1 get_index_u1() const { assert_raw_index_size(1); return *(jubyte*)(bcp()+1); } diff --git a/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.cpp b/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.cpp index 031dfb7e8ad51..7507b9c994efb 100644 --- a/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.cpp +++ b/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.cpp @@ -82,7 +82,14 @@ JfrCPUTimeTraceQueue::~JfrCPUTimeTraceQueue() { bool JfrCPUTimeTraceQueue::enqueue(JfrCPUTimeSampleRequest& request) { assert(JavaThread::current()->jfr_thread_local()->is_cpu_time_jfr_enqueue_locked(), "invariant"); assert(&JavaThread::current()->jfr_thread_local()->cpu_time_jfr_queue() == this, "invariant"); - _data[_head++] = request; + u4 elementIndex; + do { + elementIndex = AtomicAccess::load_acquire(&_head); + if (elementIndex >= _capacity) { + return false; + } + } while (AtomicAccess::cmpxchg(&_head, elementIndex, elementIndex + 1) != elementIndex); + _data[elementIndex] = request; return true; } @@ -94,19 +101,19 @@ JfrCPUTimeSampleRequest& JfrCPUTimeTraceQueue::at(u4 index) { static volatile u4 _lost_samples_sum = 0; u4 JfrCPUTimeTraceQueue::size() const { - return _head; + return AtomicAccess::load_acquire(&_head); } void JfrCPUTimeTraceQueue::set_size(u4 size) { - _head = size; + AtomicAccess::release_store(&_head, size); } u4 JfrCPUTimeTraceQueue::capacity() const { - return _capacity; + return AtomicAccess::load_acquire(&_capacity); } void JfrCPUTimeTraceQueue::set_capacity(u4 capacity) { - if (capacity == _capacity) { + if (capacity == AtomicAccess::load(&_capacity)) { return; } _head = 0; @@ -119,15 +126,15 @@ void JfrCPUTimeTraceQueue::set_capacity(u4 capacity) { } else { _data = nullptr; } - _capacity = capacity; + AtomicAccess::release_store(&_capacity, capacity); } bool JfrCPUTimeTraceQueue::is_empty() const { - return _head == 0; + return AtomicAccess::load_acquire(&_head) == 0; } u4 JfrCPUTimeTraceQueue::lost_samples() const { - return _lost_samples; + return AtomicAccess::load(&_lost_samples); } void JfrCPUTimeTraceQueue::increment_lost_samples() { @@ -136,7 +143,7 @@ void JfrCPUTimeTraceQueue::increment_lost_samples() { } void JfrCPUTimeTraceQueue::increment_lost_samples_due_to_queue_full() { - _lost_samples_due_to_queue_full++; + AtomicAccess::inc(&_lost_samples_due_to_queue_full); } u4 JfrCPUTimeTraceQueue::get_and_reset_lost_samples() { @@ -144,9 +151,7 @@ u4 JfrCPUTimeTraceQueue::get_and_reset_lost_samples() { } u4 JfrCPUTimeTraceQueue::get_and_reset_lost_samples_due_to_queue_full() { - u4 lost = _lost_samples_due_to_queue_full; - _lost_samples_due_to_queue_full = 0; - return lost; + return AtomicAccess::xchg(&_lost_samples_due_to_queue_full, (u4)0); } void JfrCPUTimeTraceQueue::init() { @@ -154,7 +159,7 @@ void JfrCPUTimeTraceQueue::init() { } void JfrCPUTimeTraceQueue::clear() { - _head = 0; + AtomicAccess::release_store(&_head, (u4)0); } void JfrCPUTimeTraceQueue::resize_if_needed() { @@ -162,8 +167,9 @@ void JfrCPUTimeTraceQueue::resize_if_needed() { if (lost_samples_due_to_queue_full == 0) { return; } - if (_capacity < CPU_TIME_QUEUE_MAX_CAPACITY) { - float ratio = (float)lost_samples_due_to_queue_full / (float)_capacity; + u4 capacity = AtomicAccess::load(&_capacity); + if (capacity < CPU_TIME_QUEUE_MAX_CAPACITY) { + float ratio = (float)lost_samples_due_to_queue_full / (float)capacity; int factor = 1; if (ratio > 8) { // idea is to quickly scale the queue in the worst case factor = ratio; @@ -175,7 +181,7 @@ void JfrCPUTimeTraceQueue::resize_if_needed() { factor = 2; } if (factor > 1) { - u4 new_capacity = MIN2(CPU_TIME_QUEUE_MAX_CAPACITY, _capacity * factor); + u4 new_capacity = MIN2(CPU_TIME_QUEUE_MAX_CAPACITY, capacity * factor); set_capacity(new_capacity); } } diff --git a/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.hpp b/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.hpp index 48fe28d22f079..e7c915fc8bed8 100644 --- a/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.hpp +++ b/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.hpp @@ -43,24 +43,19 @@ struct JfrCPUTimeSampleRequest { // Fixed size async-signal-safe SPSC linear queue backed by an array. // Designed to be only used under lock and read linearly -// The lock in question is the tri-state CPU time JFR lock in JfrThreadLocal -// This allows us to skip most of the atomic accesses and memory barriers, -// holding a lock acts as a memory barrier -// Only the _lost_samples property is atomic, as it can be accessed even after -// acquiring the lock failed. -// Important to note is that the queue is also only accessed under lock in signal -// handlers. class JfrCPUTimeTraceQueue { + // the default queue capacity, scaled if the sampling period is smaller than 10ms + // when the thread is started + static const u4 CPU_TIME_QUEUE_CAPACITY = 500; + JfrCPUTimeSampleRequest* _data; - u4 _capacity; + volatile u4 _capacity; // next unfilled index - u4 _head; + volatile u4 _head; - // the only property accessible without a lock volatile u4 _lost_samples; - - u4 _lost_samples_due_to_queue_full; + volatile u4 _lost_samples_due_to_queue_full; static const u4 CPU_TIME_QUEUE_INITIAL_CAPACITY = 20; static const u4 CPU_TIME_QUEUE_MAX_CAPACITY = 2000; @@ -87,7 +82,6 @@ class JfrCPUTimeTraceQueue { u4 lost_samples() const; - // the only method callable without holding a lock void increment_lost_samples(); void increment_lost_samples_due_to_queue_full(); diff --git a/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp b/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp index 309ae961808d5..5163bc7f6a5cb 100644 --- a/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp +++ b/src/hotspot/share/jfr/recorder/repository/jfrEmergencyDump.cpp @@ -458,7 +458,6 @@ const char* JfrEmergencyDump::chunk_path(const char* repository_path) { */ static void release_locks(Thread* thread) { assert(thread != nullptr, "invariant"); - assert(!thread->is_Java_thread() || JavaThread::cast(thread)->thread_state() == _thread_in_vm, "invariant"); #ifdef ASSERT Mutex* owned_lock = thread->owned_locks(); @@ -520,14 +519,13 @@ static void release_locks(Thread* thread) { class JavaThreadInVMAndNative : public StackObj { private: - JavaThread* _jt; + JavaThread* const _jt; JavaThreadState _original_state; public: - JavaThreadInVMAndNative(Thread* t) : _jt(nullptr), + JavaThreadInVMAndNative(Thread* t) : _jt(t->is_Java_thread() ? JavaThread::cast(t) : nullptr), _original_state(_thread_max_state) { - if (t != nullptr && t->is_Java_thread()) { - _jt = JavaThread::cast(t); + if (_jt != nullptr) { _original_state = _jt->thread_state(); if (_original_state != _thread_in_vm) { _jt->set_thread_state(_thread_in_vm); @@ -537,7 +535,6 @@ class JavaThreadInVMAndNative : public StackObj { ~JavaThreadInVMAndNative() { if (_original_state != _thread_max_state) { - assert(_jt != nullptr, "invariant"); _jt->set_thread_state(_original_state); } } @@ -577,13 +574,11 @@ static bool guard_reentrancy() { Thread* const thread = Thread::current_or_null_safe(); const traceid tid = thread != nullptr ? JFR_JVM_THREAD_ID(thread) : max_julong; if (AtomicAccess::cmpxchg(&_jfr_shutdown_tid, shutdown_tid, tid) != shutdown_tid) { - JavaThreadInVMAndNative jtivm(thread); if (thread != nullptr) { + JavaThreadInVMAndNative jtivm(thread); release_locks(thread); } log_info(jfr, system)("A jfr emergency dump is already in progress, waiting for thread id " UINT64_FORMAT_X, AtomicAccess::load(&_jfr_shutdown_tid)); - // Transition to a safe safepoint state for the infinite sleep. A nop for non-java threads. - jtivm.transition_to_native(); os::infinite_sleep(); // stay here until we exit normally or crash. ShouldNotReachHere(); } diff --git a/src/hotspot/share/logging/logTag.hpp b/src/hotspot/share/logging/logTag.hpp index 3ad6a197d07d3..6d0bd117ad91d 100644 --- a/src/hotspot/share/logging/logTag.hpp +++ b/src/hotspot/share/logging/logTag.hpp @@ -41,7 +41,6 @@ class outputStream; LOG_TAG(aot) \ LOG_TAG(arguments) \ LOG_TAG(array) \ - LOG_TAG(asan) \ LOG_TAG(attach) \ LOG_TAG(barrier) \ LOG_TAG(blocks) \ diff --git a/src/hotspot/share/memory/arena.cpp b/src/hotspot/share/memory/arena.cpp index b9968083e0e85..db0bb8add21dc 100644 --- a/src/hotspot/share/memory/arena.cpp +++ b/src/hotspot/share/memory/arena.cpp @@ -39,26 +39,19 @@ // It is used very early in the vm initialization, in allocation // code and other areas. For many calls, the current thread has not // been created so we cannot use Mutex. -static DeferredStatic GlobalChunkPoolMutex; +static PlatformMutex* GlobalChunkPoolMutex = nullptr; void Arena::initialize_chunk_pool() { - GlobalChunkPoolMutex.initialize(); + GlobalChunkPoolMutex = new PlatformMutex(); } -ChunkPoolLocker::ChunkPoolLocker(LockStrategy ls) { - if (ls == LockStrategy::Lock) { - GlobalChunkPoolMutex->lock(); - _locked = true; - } else { - assert(ls == LockStrategy::Try, "must be"); - _locked = GlobalChunkPoolMutex->try_lock(); - } +ChunkPoolLocker::ChunkPoolLocker() { + assert(GlobalChunkPoolMutex != nullptr, "must be initialized"); + GlobalChunkPoolMutex->lock(); }; ChunkPoolLocker::~ChunkPoolLocker() { - if (_locked) { - GlobalChunkPoolMutex->unlock(); - } + GlobalChunkPoolMutex->unlock(); }; // Pre-defined default chunk sizes must be arena-aligned, see Chunk::operator new() diff --git a/src/hotspot/share/memory/arena.hpp b/src/hotspot/share/memory/arena.hpp index b4a0546babf83..e2169ee406e78 100644 --- a/src/hotspot/share/memory/arena.hpp +++ b/src/hotspot/share/memory/arena.hpp @@ -38,11 +38,8 @@ #define ARENA_ALIGN(x) (align_up((x), ARENA_AMALLOC_ALIGNMENT)) class ChunkPoolLocker : public StackObj { - bool _locked; public: - enum class LockStrategy { Lock, Try }; - - ChunkPoolLocker(LockStrategy ls = LockStrategy::Lock); + ChunkPoolLocker(); ~ChunkPoolLocker(); }; diff --git a/src/hotspot/share/memory/universe.cpp b/src/hotspot/share/memory/universe.cpp index 756619bff3386..424e43c5e83ce 100644 --- a/src/hotspot/share/memory/universe.cpp +++ b/src/hotspot/share/memory/universe.cpp @@ -955,7 +955,7 @@ void Universe::initialize_tlab() { } } -ReservedHeapSpace Universe::reserve_heap(size_t heap_size, size_t alignment, size_t desired_page_size) { +ReservedHeapSpace Universe::reserve_heap(size_t heap_size, size_t alignment) { assert(alignment <= Arguments::conservative_max_heap_alignment(), "actual alignment %zu must be within maximum heap alignment %zu", @@ -966,21 +966,15 @@ ReservedHeapSpace Universe::reserve_heap(size_t heap_size, size_t alignment, siz assert(!UseCompressedOops || (total_reserved <= (OopEncodingHeapMax - os::vm_page_size())), "heap size is too big for compressed oops"); - size_t page_size; - if (desired_page_size == 0) { - if (UseLargePages) { - page_size = os::large_page_size(); - } else { - page_size = os::vm_page_size(); - } + size_t page_size = os::vm_page_size(); + if (UseLargePages && is_aligned(alignment, os::large_page_size())) { + page_size = os::large_page_size(); } else { // Parallel is the only collector that might opt out of using large pages // for the heap. - assert(UseParallelGC , "only Parallel"); - // Use caller provided value. - page_size = desired_page_size; + assert(!UseLargePages || UseParallelGC , "Wrong alignment to use large pages"); } - assert(is_aligned(heap_size, page_size), "inv"); + // Now create the space. ReservedHeapSpace rhs = HeapReserver::reserve(total_reserved, alignment, page_size, AllocateHeapAt); diff --git a/src/hotspot/share/memory/universe.hpp b/src/hotspot/share/memory/universe.hpp index 37ca965062e80..3b1f2523ed845 100644 --- a/src/hotspot/share/memory/universe.hpp +++ b/src/hotspot/share/memory/universe.hpp @@ -315,7 +315,7 @@ class Universe: AllStatic { DEBUG_ONLY(static bool is_in_heap_or_null(const void* p) { return p == nullptr || is_in_heap(p); }) // Reserve Java heap and determine CompressedOops mode - static ReservedHeapSpace reserve_heap(size_t heap_size, size_t alignment, size_t desired_page_size = 0); + static ReservedHeapSpace reserve_heap(size_t heap_size, size_t alignment); // Global OopStorages static OopStorage* vm_weak(); diff --git a/src/hotspot/share/nmt/mallocHeader.cpp b/src/hotspot/share/nmt/mallocHeader.cpp index d88b5c790fbaa..2b59a2b66480f 100644 --- a/src/hotspot/share/nmt/mallocHeader.cpp +++ b/src/hotspot/share/nmt/mallocHeader.cpp @@ -26,7 +26,6 @@ #include "nmt/mallocHeader.inline.hpp" #include "nmt/mallocSiteTable.hpp" #include "nmt/memTag.hpp" -#include "nmt/memTracker.hpp" #include "runtime/os.hpp" #include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" @@ -37,7 +36,7 @@ // fitting into eight bits. STATIC_ASSERT(sizeof(MemTag) == sizeof(uint8_t)); -void MallocHeader::print_block_on_error(outputStream* st, address bad_address, address block_address) const { +void MallocHeader::print_block_on_error(outputStream* st, address bad_address) const { assert(bad_address >= (address)this, "sanity"); // This function prints block information, including hex dump, in case of a detected @@ -49,18 +48,6 @@ void MallocHeader::print_block_on_error(outputStream* st, address bad_address, a st->print_cr("NMT Block at " PTR_FORMAT ", corruption at: " PTR_FORMAT ": ", p2i(this), p2i(bad_address)); - if (MemTracker::tracking_level() == NMT_TrackingLevel::NMT_detail) { - MallocHeader* mh = (MallocHeader*)block_address; - NativeCallStack stack; - if (MallocSiteTable::access_stack(stack, *mh)) { - st->print_cr("allocated from:"); - stack.print_on(st); - } else { - st->print_cr("allocation-site cannot be shown since the marker is also corrupted."); - } - st->print_cr(""); - } - static const size_t min_dump_length = 256; address from1 = align_down((address)this, sizeof(void*)) - (min_dump_length / 2); address to1 = from1 + min_dump_length; diff --git a/src/hotspot/share/nmt/mallocHeader.hpp b/src/hotspot/share/nmt/mallocHeader.hpp index acfc74012682f..8472b5f8ce888 100644 --- a/src/hotspot/share/nmt/mallocHeader.hpp +++ b/src/hotspot/share/nmt/mallocHeader.hpp @@ -106,7 +106,7 @@ class MallocHeader { // We discount sizes larger than these static const size_t max_reasonable_malloc_size = LP64_ONLY(256 * G) NOT_LP64(3500 * M); - void print_block_on_error(outputStream* st, address bad_address, address block_address) const; + void print_block_on_error(outputStream* st, address bad_address) const; static uint16_t build_footer(uint8_t b1, uint8_t b2) { return (uint16_t)(((uint16_t)b1 << 8) | (uint16_t)b2); } diff --git a/src/hotspot/share/nmt/mallocHeader.inline.hpp b/src/hotspot/share/nmt/mallocHeader.inline.hpp index 7bc8a25028c51..8b1862332fc37 100644 --- a/src/hotspot/share/nmt/mallocHeader.inline.hpp +++ b/src/hotspot/share/nmt/mallocHeader.inline.hpp @@ -103,7 +103,7 @@ inline OutTypeParam MallocHeader::resolve_checked_impl(InTypeParam memblock) { } OutTypeParam header_pointer = (OutTypeParam)memblock - 1; if (!header_pointer->check_block_integrity(msg, sizeof(msg), &corruption)) { - header_pointer->print_block_on_error(tty, corruption != nullptr ? corruption : (address)header_pointer, (address)header_pointer); + header_pointer->print_block_on_error(tty, corruption != nullptr ? corruption : (address)header_pointer); fatal("NMT has detected a memory corruption bug. Block at " PTR_FORMAT ": %s", p2i(memblock), msg); } return header_pointer; diff --git a/src/hotspot/share/nmt/mallocSiteTable.cpp b/src/hotspot/share/nmt/mallocSiteTable.cpp index 0150a25cae3a4..c9ddffce5ecb7 100644 --- a/src/hotspot/share/nmt/mallocSiteTable.cpp +++ b/src/hotspot/share/nmt/mallocSiteTable.cpp @@ -163,17 +163,13 @@ MallocSite* MallocSiteTable::lookup_or_add(const NativeCallStack& key, uint32_t* // Access malloc site MallocSite* MallocSiteTable::malloc_site(uint32_t marker) { uint16_t bucket_idx = bucket_idx_from_marker(marker); - if (bucket_idx >= table_size) { - return nullptr; - } + assert(bucket_idx < table_size, "Invalid bucket index"); const uint16_t pos_idx = pos_idx_from_marker(marker); MallocSiteHashtableEntry* head = _table[bucket_idx]; for (size_t index = 0; index < pos_idx && head != nullptr; index++, head = (MallocSiteHashtableEntry*)head->next()) {} - if (head == nullptr) { - return nullptr; - } + assert(head != nullptr, "Invalid position index"); return head->data(); } diff --git a/src/hotspot/share/nmt/mallocTracker.cpp b/src/hotspot/share/nmt/mallocTracker.cpp index a61a27db25d2f..75089dffc3014 100644 --- a/src/hotspot/share/nmt/mallocTracker.cpp +++ b/src/hotspot/share/nmt/mallocTracker.cpp @@ -65,11 +65,7 @@ void MallocMemorySnapshot::copy_to(MallocMemorySnapshot* s) { // Use lock to make sure that mtChunks don't get deallocated while the // copy is going on, because their size is adjusted using this // buffer in make_adjustment(). - ChunkPoolLocker::LockStrategy ls = ChunkPoolLocker::LockStrategy::Lock; - if (VMError::is_error_reported() && VMError::is_error_reported_in_current_thread()) { - ls = ChunkPoolLocker::LockStrategy::Try; - } - ChunkPoolLocker cpl(ls); + ChunkPoolLocker lock; s->_all_mallocs = _all_mallocs; size_t total_size = 0; size_t total_count = 0; diff --git a/src/hotspot/share/nmt/nmtUsage.cpp b/src/hotspot/share/nmt/nmtUsage.cpp index 9e6fc3e183bac..3a9a232a36eea 100644 --- a/src/hotspot/share/nmt/nmtUsage.cpp +++ b/src/hotspot/share/nmt/nmtUsage.cpp @@ -30,7 +30,6 @@ #include "nmt/nmtUsage.hpp" #include "nmt/threadStackTracker.hpp" #include "runtime/mutexLocker.hpp" -#include "utilities/vmError.hpp" // Enabled all options for snapshot. const NMTUsageOptions NMTUsage::OptionsAll = { true, true, true }; @@ -59,11 +58,7 @@ void NMTUsage::update_malloc_usage() { // Lock needed to keep values in sync, total area size // is deducted from mtChunk in the end to give correct values. { - ChunkPoolLocker::LockStrategy ls = ChunkPoolLocker::LockStrategy::Lock; - if (VMError::is_error_reported() && VMError::is_error_reported_in_current_thread()) { - ls = ChunkPoolLocker::LockStrategy::Try; - } - ChunkPoolLocker cpl(ls); + ChunkPoolLocker lock; ms = MallocMemorySummary::as_snapshot(); } diff --git a/src/hotspot/share/oops/constantPool.cpp b/src/hotspot/share/oops/constantPool.cpp index b072c7f26ec53..5d5c05482156b 100644 --- a/src/hotspot/share/oops/constantPool.cpp +++ b/src/hotspot/share/oops/constantPool.cpp @@ -538,23 +538,18 @@ void ConstantPool::remove_resolved_klass_if_non_deterministic(int cp_index) { assert(ArchiveBuilder::current()->is_in_buffer_space(this), "must be"); assert(tag_at(cp_index).is_klass(), "must be resolved"); + Klass* k = resolved_klass_at(cp_index); bool can_archive; - Klass* k = nullptr; - if (CDSConfig::is_dumping_preimage_static_archive()) { + if (k == nullptr) { + // We'd come here if the referenced class has been excluded via + // SystemDictionaryShared::is_excluded_class(). As a result, ArchiveBuilder + // has cleared the resolved_klasses()->at(...) pointer to null. Thus, we + // need to revert the tag to JVM_CONSTANT_UnresolvedClass. can_archive = false; } else { - k = resolved_klass_at(cp_index); - if (k == nullptr) { - // We'd come here if the referenced class has been excluded via - // SystemDictionaryShared::is_excluded_class(). As a result, ArchiveBuilder - // has cleared the resolved_klasses()->at(...) pointer to null. Thus, we - // need to revert the tag to JVM_CONSTANT_UnresolvedClass. - can_archive = false; - } else { - ConstantPool* src_cp = ArchiveBuilder::current()->get_source_addr(this); - can_archive = AOTConstantPoolResolver::is_resolution_deterministic(src_cp, cp_index); - } + ConstantPool* src_cp = ArchiveBuilder::current()->get_source_addr(this); + can_archive = AOTConstantPoolResolver::is_resolution_deterministic(src_cp, cp_index); } if (!can_archive) { diff --git a/src/hotspot/share/oops/cpCache.cpp b/src/hotspot/share/oops/cpCache.cpp index f60229dbfffc2..941ceac8de12b 100644 --- a/src/hotspot/share/oops/cpCache.cpp +++ b/src/hotspot/share/oops/cpCache.cpp @@ -430,25 +430,26 @@ void ConstantPoolCache::remove_resolved_field_entries_if_non_deterministic() { bool archived = false; bool resolved = rfi->is_resolved(Bytecodes::_getfield) || rfi->is_resolved(Bytecodes::_putfield); - if (resolved && !CDSConfig::is_dumping_preimage_static_archive() - && AOTConstantPoolResolver::is_resolution_deterministic(src_cp, cp_index)) { + if (resolved && AOTConstantPoolResolver::is_resolution_deterministic(src_cp, cp_index)) { rfi->mark_and_relocate(); archived = true; } else { rfi->remove_unshareable_info(); } - LogStreamHandle(Trace, aot, resolve) log; - if (log.is_enabled()) { - ResourceMark rm; - int klass_cp_index = cp->uncached_klass_ref_index_at(cp_index); - Symbol* klass_name = cp->klass_name_at(klass_cp_index); - Symbol* name = cp->uncached_name_ref_at(cp_index); - Symbol* signature = cp->uncached_signature_ref_at(cp_index); - log.print("%s field CP entry [%3d]: %s => %s.%s:%s", - (archived ? "archived" : "reverted"), - cp_index, - cp->pool_holder()->name()->as_C_string(), - klass_name->as_C_string(), name->as_C_string(), signature->as_C_string()); + if (resolved) { + LogStreamHandle(Trace, aot, resolve) log; + if (log.is_enabled()) { + ResourceMark rm; + int klass_cp_index = cp->uncached_klass_ref_index_at(cp_index); + Symbol* klass_name = cp->klass_name_at(klass_cp_index); + Symbol* name = cp->uncached_name_ref_at(cp_index); + Symbol* signature = cp->uncached_signature_ref_at(cp_index); + log.print("%s field CP entry [%3d]: %s => %s.%s:%s", + (archived ? "archived" : "reverted"), + cp_index, + cp->pool_holder()->name()->as_C_string(), + klass_name->as_C_string(), name->as_C_string(), signature->as_C_string()); + } } ArchiveBuilder::alloc_stats()->record_field_cp_entry(archived, resolved && !archived); } @@ -469,31 +470,32 @@ void ConstantPoolCache::remove_resolved_method_entries_if_non_deterministic() { // Just for safety -- this should not happen, but do not archive if we ever see this. resolved &= !(rme->is_resolved(Bytecodes::_invokestatic)); - if (resolved && !CDSConfig::is_dumping_preimage_static_archive() - && can_archive_resolved_method(src_cp, rme)) { + if (resolved && can_archive_resolved_method(src_cp, rme)) { rme->mark_and_relocate(src_cp); archived = true; } else { rme->remove_unshareable_info(); } - LogStreamHandle(Trace, aot, resolve) log; - if (log.is_enabled()) { - ResourceMark rm; - int klass_cp_index = cp->uncached_klass_ref_index_at(cp_index); - Symbol* klass_name = cp->klass_name_at(klass_cp_index); - Symbol* name = cp->uncached_name_ref_at(cp_index); - Symbol* signature = cp->uncached_signature_ref_at(cp_index); - log.print("%s%s method CP entry [%3d]: %s %s.%s:%s", - (archived ? "archived" : "reverted"), - (rme->is_resolved(Bytecodes::_invokeinterface) ? " interface" : ""), - cp_index, - cp->pool_holder()->name()->as_C_string(), - klass_name->as_C_string(), name->as_C_string(), signature->as_C_string()); - if (archived) { - Klass* resolved_klass = cp->resolved_klass_at(klass_cp_index); - log.print(" => %s%s", - resolved_klass->name()->as_C_string(), - (rme->is_resolved(Bytecodes::_invokestatic) ? " *** static" : "")); + if (resolved) { + LogStreamHandle(Trace, aot, resolve) log; + if (log.is_enabled()) { + ResourceMark rm; + int klass_cp_index = cp->uncached_klass_ref_index_at(cp_index); + Symbol* klass_name = cp->klass_name_at(klass_cp_index); + Symbol* name = cp->uncached_name_ref_at(cp_index); + Symbol* signature = cp->uncached_signature_ref_at(cp_index); + log.print("%s%s method CP entry [%3d]: %s %s.%s:%s", + (archived ? "archived" : "reverted"), + (rme->is_resolved(Bytecodes::_invokeinterface) ? " interface" : ""), + cp_index, + cp->pool_holder()->name()->as_C_string(), + klass_name->as_C_string(), name->as_C_string(), signature->as_C_string()); + if (archived) { + Klass* resolved_klass = cp->resolved_klass_at(klass_cp_index); + log.print(" => %s%s", + resolved_klass->name()->as_C_string(), + (rme->is_resolved(Bytecodes::_invokestatic) ? " *** static" : "")); + } } ArchiveBuilder::alloc_stats()->record_method_cp_entry(archived, resolved && !archived); } @@ -508,28 +510,29 @@ void ConstantPoolCache::remove_resolved_indy_entries_if_non_deterministic() { int cp_index = rei->constant_pool_index(); bool archived = false; bool resolved = rei->is_resolved(); - if (resolved && !CDSConfig::is_dumping_preimage_static_archive() - && AOTConstantPoolResolver::is_resolution_deterministic(src_cp, cp_index)) { + if (resolved && AOTConstantPoolResolver::is_resolution_deterministic(src_cp, cp_index)) { rei->mark_and_relocate(); archived = true; } else { rei->remove_unshareable_info(); } - LogStreamHandle(Trace, aot, resolve) log; - if (log.is_enabled()) { - ResourceMark rm; - int bsm = cp->bootstrap_method_ref_index_at(cp_index); - int bsm_ref = cp->method_handle_index_at(bsm); - Symbol* bsm_name = cp->uncached_name_ref_at(bsm_ref); - Symbol* bsm_signature = cp->uncached_signature_ref_at(bsm_ref); - Symbol* bsm_klass = cp->klass_name_at(cp->uncached_klass_ref_index_at(bsm_ref)); - log.print("%s indy CP entry [%3d]: %s (%d)", - (archived ? "archived" : "reverted"), - cp_index, cp->pool_holder()->name()->as_C_string(), i); - log.print(" %s %s.%s:%s", (archived ? "=>" : " "), bsm_klass->as_C_string(), - bsm_name->as_C_string(), bsm_signature->as_C_string()); + if (resolved) { + LogStreamHandle(Trace, aot, resolve) log; + if (log.is_enabled()) { + ResourceMark rm; + int bsm = cp->bootstrap_method_ref_index_at(cp_index); + int bsm_ref = cp->method_handle_index_at(bsm); + Symbol* bsm_name = cp->uncached_name_ref_at(bsm_ref); + Symbol* bsm_signature = cp->uncached_signature_ref_at(bsm_ref); + Symbol* bsm_klass = cp->klass_name_at(cp->uncached_klass_ref_index_at(bsm_ref)); + log.print("%s indy CP entry [%3d]: %s (%d)", + (archived ? "archived" : "reverted"), + cp_index, cp->pool_holder()->name()->as_C_string(), i); + log.print(" %s %s.%s:%s", (archived ? "=>" : " "), bsm_klass->as_C_string(), + bsm_name->as_C_string(), bsm_signature->as_C_string()); + } + ArchiveBuilder::alloc_stats()->record_indy_cp_entry(archived, resolved && !archived); } - ArchiveBuilder::alloc_stats()->record_indy_cp_entry(archived, resolved && !archived); } } diff --git a/src/hotspot/share/opto/callnode.cpp b/src/hotspot/share/opto/callnode.cpp index ad6548a649e88..ef1ebc5cef949 100644 --- a/src/hotspot/share/opto/callnode.cpp +++ b/src/hotspot/share/opto/callnode.cpp @@ -72,7 +72,7 @@ void StartNode::calling_convention(BasicType* sig_bt, VMRegPair *parm_regs, uint //------------------------------Registers-------------------------------------- const RegMask &StartNode::in_RegMask(uint) const { - return RegMask::EMPTY; + return RegMask::Empty; } //------------------------------match------------------------------------------ @@ -82,7 +82,7 @@ Node *StartNode::match( const ProjNode *proj, const Matcher *match ) { case TypeFunc::Control: case TypeFunc::I_O: case TypeFunc::Memory: - return new MachProjNode(this,proj->_con,RegMask::EMPTY,MachProjNode::unmatched_proj); + return new MachProjNode(this,proj->_con,RegMask::Empty,MachProjNode::unmatched_proj); case TypeFunc::FramePtr: return new MachProjNode(this,proj->_con,Matcher::c_frame_ptr_mask, Op_RegP); case TypeFunc::ReturnAdr: @@ -777,12 +777,12 @@ Node *CallNode::match( const ProjNode *proj, const Matcher *match ) { case TypeFunc::Control: case TypeFunc::I_O: case TypeFunc::Memory: - return new MachProjNode(this,proj->_con,RegMask::EMPTY,MachProjNode::unmatched_proj); + return new MachProjNode(this,proj->_con,RegMask::Empty,MachProjNode::unmatched_proj); case TypeFunc::Parms+1: // For LONG & DOUBLE returns assert(tf()->range()->field_at(TypeFunc::Parms+1) == Type::HALF, ""); // 2nd half of doubles and longs - return new MachProjNode(this,proj->_con, RegMask::EMPTY, (uint)OptoReg::Bad); + return new MachProjNode(this,proj->_con, RegMask::Empty, (uint)OptoReg::Bad); case TypeFunc::Parms: { // Normal returns uint ideal_reg = tf()->range()->field_at(TypeFunc::Parms)->ideal_reg(); @@ -798,14 +798,14 @@ Node *CallNode::match( const ProjNode *proj, const Matcher *match ) { if(ideal_reg >= Op_VecA && ideal_reg <= Op_VecZ) { if(OptoReg::is_valid(regs.second())) { for (OptoReg::Name r = regs.first(); r <= regs.second(); r = OptoReg::add(r, 1)) { - rm.insert(r); + rm.Insert(r); } } } } if( OptoReg::is_valid(regs.second()) ) - rm.insert(regs.second()); + rm.Insert( regs.second() ); return new MachProjNode(this,proj->_con,rm,ideal_reg); } @@ -1492,14 +1492,12 @@ void SafePointNode::dump_spec(outputStream *st) const { #endif const RegMask &SafePointNode::in_RegMask(uint idx) const { - if (idx < TypeFunc::Parms) { - return RegMask::EMPTY; - } + if( idx < TypeFunc::Parms ) return RegMask::Empty; // Values outside the domain represent debug info return *(Compile::current()->matcher()->idealreg2debugmask[in(idx)->ideal_reg()]); } const RegMask &SafePointNode::out_RegMask() const { - return RegMask::EMPTY; + return RegMask::Empty; } @@ -1610,7 +1608,7 @@ const RegMask &SafePointScalarObjectNode::in_RegMask(uint idx) const { } const RegMask &SafePointScalarObjectNode::out_RegMask() const { - return RegMask::EMPTY; + return RegMask::Empty; } uint SafePointScalarObjectNode::match_edge(uint idx) const { @@ -1661,7 +1659,7 @@ const RegMask &SafePointScalarMergeNode::in_RegMask(uint idx) const { } const RegMask &SafePointScalarMergeNode::out_RegMask() const { - return RegMask::EMPTY; + return RegMask::Empty; } uint SafePointScalarMergeNode::match_edge(uint idx) const { diff --git a/src/hotspot/share/opto/cfgnode.cpp b/src/hotspot/share/opto/cfgnode.cpp index 0293f42d79123..ef912ff471ac3 100644 --- a/src/hotspot/share/opto/cfgnode.cpp +++ b/src/hotspot/share/opto/cfgnode.cpp @@ -1014,7 +1014,7 @@ bool RegionNode::optimize_trichotomy(PhaseIterGVN* igvn) { } const RegMask &RegionNode::out_RegMask() const { - return RegMask::EMPTY; + return RegMask::Empty; } #ifndef PRODUCT @@ -2859,15 +2859,13 @@ bool PhiNode::is_tripcount(BasicType bt) const { //------------------------------out_RegMask------------------------------------ const RegMask &PhiNode::in_RegMask(uint i) const { - return i ? out_RegMask() : RegMask::EMPTY; + return i ? out_RegMask() : RegMask::Empty; } const RegMask &PhiNode::out_RegMask() const { uint ideal_reg = _type->ideal_reg(); assert( ideal_reg != Node::NotAMachineReg, "invalid type at Phi" ); - if (ideal_reg == 0) { - return RegMask::EMPTY; - } + if( ideal_reg == 0 ) return RegMask::Empty; assert(ideal_reg != Op_RegFlags, "flags register is not spillable"); return *(Compile::current()->matcher()->idealreg2spillmask[ideal_reg]); } @@ -2894,22 +2892,22 @@ Node* GotoNode::Identity(PhaseGVN* phase) { } const RegMask &GotoNode::out_RegMask() const { - return RegMask::EMPTY; + return RegMask::Empty; } //============================================================================= const RegMask &JumpNode::out_RegMask() const { - return RegMask::EMPTY; + return RegMask::Empty; } //============================================================================= const RegMask &JProjNode::out_RegMask() const { - return RegMask::EMPTY; + return RegMask::Empty; } //============================================================================= const RegMask &CProjNode::out_RegMask() const { - return RegMask::EMPTY; + return RegMask::Empty; } diff --git a/src/hotspot/share/opto/cfgnode.hpp b/src/hotspot/share/opto/cfgnode.hpp index 78ad085e03dbf..fffe00a4114c7 100644 --- a/src/hotspot/share/opto/cfgnode.hpp +++ b/src/hotspot/share/opto/cfgnode.hpp @@ -741,7 +741,7 @@ class BlackholeNode : public MultiNode { // Fake the incoming arguments mask for blackholes: accept all registers // and all stack slots. This would avoid any redundant register moves // for blackhole inputs. - return RegMask::ALL; + return RegMask::All; } #ifndef PRODUCT virtual void format(PhaseRegAlloc* ra, outputStream* st) const; diff --git a/src/hotspot/share/opto/chaitin.cpp b/src/hotspot/share/opto/chaitin.cpp index 903203bd0944e..45a913506266e 100644 --- a/src/hotspot/share/opto/chaitin.cpp +++ b/src/hotspot/share/opto/chaitin.cpp @@ -49,11 +49,9 @@ void LRG::dump() const { _mask.dump(); if( _msize_valid ) { if( mask_size() == compute_mask_size() ) tty->print(", #%d ",_mask_size); - else { - tty->print(", #!!!_%d_vs_%d ", _mask_size, _mask.size()); - } + else tty->print(", #!!!_%d_vs_%d ",_mask_size,_mask.Size()); } else { - tty->print(", #?(%d) ", _mask.size()); + tty->print(", #?(%d) ",_mask.Size()); } tty->print("EffDeg: "); @@ -743,7 +741,7 @@ void PhaseChaitin::Register_Allocate() { } } else { // Misaligned; extract 2 bits OptoReg::Name hi = lrg.reg(); // Get hi register - lrg.remove(hi); // Yank from mask + lrg.Remove(hi); // Yank from mask int lo = lrg.mask().find_first_elem(); // Find lo set_pair(i, hi, lo); } @@ -775,7 +773,7 @@ void PhaseChaitin::de_ssa() { Node *n = block->get_node(j); // Pre-color to the zero live range, or pick virtual register const RegMask &rm = n->out_RegMask(); - _lrg_map.map(n->_idx, !rm.is_empty() ? lr_counter++ : 0); + _lrg_map.map(n->_idx, !rm.is_Empty() ? lr_counter++ : 0); } } @@ -796,7 +794,7 @@ void PhaseChaitin::mark_ssa() { Node *n = block->get_node(j); // Pre-color to the zero live range, or pick virtual register const RegMask &rm = n->out_RegMask(); - _lrg_map.map(n->_idx, !rm.is_empty() ? n->_idx : 0); + _lrg_map.map(n->_idx, !rm.is_Empty() ? n->_idx : 0); max_idx = (n->_idx > max_idx) ? n->_idx : max_idx; } } @@ -881,7 +879,7 @@ void PhaseChaitin::gather_lrg_masks( bool after_aggressive ) { // Limit result register mask to acceptable registers const RegMask &rm = n->out_RegMask(); - lrg.and_with(rm); + lrg.AND( rm ); uint ireg = n->ideal_reg(); assert( !n->bottom_type()->isa_oop_ptr() || ireg == Op_RegP, @@ -937,7 +935,7 @@ void PhaseChaitin::gather_lrg_masks( bool after_aggressive ) { switch (ireg) { case MachProjNode::fat_proj: // Fat projections have size equal to number of registers killed - lrg.set_num_regs(rm.size()); + lrg.set_num_regs(rm.Size()); lrg.set_reg_pressure(lrg.num_regs()); lrg._fat_proj = 1; lrg._is_bound = 1; @@ -1128,7 +1126,7 @@ void PhaseChaitin::gather_lrg_masks( bool after_aggressive ) { // Later, AFTER aggressive, this live range will have to spill // but the spiller handles slow-path calls very nicely. } else { - lrg.and_with(rm); + lrg.AND( rm ); } // Check for bound register masks @@ -1166,7 +1164,7 @@ void PhaseChaitin::gather_lrg_masks( bool after_aggressive ) { if (!is_vect && !n->is_SpillCopy() && (lrg._def == nullptr || lrg.is_multidef() || !lrg._def->is_SpillCopy()) && lrgmask.is_misaligned_pair()) { - lrg.clear(); + lrg.Clear(); } // Check for maximum frequency value @@ -1407,7 +1405,7 @@ void PhaseChaitin::Simplify( ) { // Is 'reg' register legal for 'lrg'? static bool is_legal_reg(LRG& lrg, OptoReg::Name reg) { - if (lrg.mask().can_represent(reg) && lrg.mask().member(reg)) { + if (lrg.mask().can_represent(reg) && lrg.mask().Member(reg)) { // RA uses OptoReg which represent the highest element of a registers set. // For example, vectorX (128bit) on x86 uses [XMM,XMMb,XMMc,XMMd] set // in which XMMd is used by RA to represent such vectors. A double value @@ -1461,7 +1459,7 @@ static OptoReg::Name find_first_set(LRG& lrg, RegMask& mask) { return assigned; } else { // Remove more for each iteration - mask.remove(assigned - num_regs + 1); // Unmask the lowest reg + mask.Remove(assigned - num_regs + 1); // Unmask the lowest reg mask.clear_to_sets(RegMask::SlotsPerVecA); // Align by SlotsPerVecA bits assigned = mask.find_first_set(lrg, num_regs); } @@ -1512,7 +1510,7 @@ OptoReg::Name PhaseChaitin::bias_color(LRG& lrg) { // Choose a color which is legal for him ResourceMark rm(C->regmask_arena()); RegMask tempmask(lrg.mask(), C->regmask_arena()); - tempmask.and_with(lrgs(copy_lrg).mask()); + tempmask.AND(lrgs(copy_lrg).mask()); tempmask.clear_to_sets(lrg.num_regs()); OptoReg::Name reg = find_first_set(lrg, tempmask); if (OptoReg::is_valid(reg)) @@ -1535,9 +1533,9 @@ OptoReg::Name PhaseChaitin::bias_color(LRG& lrg) { if( (++_alternate & 1) && OptoReg::is_valid(reg) ) { // This 'Remove; find; Insert' idiom is an expensive way to find the // SECOND element in the mask. - lrg.remove(reg); + lrg.Remove(reg); OptoReg::Name reg2 = lrg.mask().find_first_elem(); - lrg.insert(reg); + lrg.Insert(reg); if (OptoReg::is_reg(reg2)) { reg = reg2; } @@ -1547,8 +1545,8 @@ OptoReg::Name PhaseChaitin::bias_color(LRG& lrg) { // Choose a color in the current chunk OptoReg::Name PhaseChaitin::choose_color(LRG& lrg) { - assert(C->in_preserve_stack_slots() == 0 || lrg.mask().is_offset() || lrg._is_bound || lrg.mask().is_bound1() || !lrg.mask().member(OptoReg::Name(_matcher._old_SP - 1)), "must not allocate stack0 (inside preserve area)"); - assert(C->out_preserve_stack_slots() == 0 || lrg.mask().is_offset() || lrg._is_bound || lrg.mask().is_bound1() || !lrg.mask().member(OptoReg::Name(_matcher._old_SP + 0)), "must not allocate stack0 (inside preserve area)"); + assert(C->in_preserve_stack_slots() == 0 || lrg.mask().is_offset() || lrg._is_bound || lrg.mask().is_bound1() || !lrg.mask().Member(OptoReg::Name(_matcher._old_SP - 1)), "must not allocate stack0 (inside preserve area)"); + assert(C->out_preserve_stack_slots() == 0 || lrg.mask().is_offset() || lrg._is_bound || lrg.mask().is_bound1() || !lrg.mask().Member(OptoReg::Name(_matcher._old_SP + 0)), "must not allocate stack0 (inside preserve area)"); if( lrg.num_regs() == 1 || // Common Case !lrg._fat_proj ) // Aligned+adjacent pairs ok @@ -1624,20 +1622,20 @@ uint PhaseChaitin::Select( ) { // at retry_next_chunk. if (nreg < LRG::SPILL_REG) { #ifndef PRODUCT - uint size = lrg->mask().size(); + uint size = lrg->mask().Size(); ResourceMark rm(C->regmask_arena()); RegMask trace_mask(lrg->mask(), C->regmask_arena()); #endif - lrg->subtract_inner(nlrg.mask()); + lrg->SUBTRACT_inner(nlrg.mask()); #ifndef PRODUCT - if (trace_spilling() && lrg->mask().size() != size) { + if (trace_spilling() && lrg->mask().Size() != size) { ttyLocker ttyl; tty->print("L%d ", lidx); trace_mask.dump(); tty->print(" intersected L%d ", neighbor); nlrg.mask().dump(); tty->print(" removed "); - trace_mask.subtract(lrg->mask()); + trace_mask.SUBTRACT(lrg->mask()); trace_mask.dump(); tty->print(" leaving "); lrg->mask().dump(); @@ -1703,15 +1701,15 @@ uint PhaseChaitin::Select( ) { } else { assert(!lrg->_is_vector || n_regs <= RegMask::SlotsPerVecZ, "sanity"); } - lrg->clear(); // Clear the mask - lrg->insert(reg); // Set regmask to match selected reg + lrg->Clear(); // Clear the mask + lrg->Insert(reg); // Set regmask to match selected reg // For vectors and pairs, also insert the low bit of the pair // We always choose the high bit, then mask the low bits by register size if (lrg->is_scalable() && OptoReg::is_stack(lrg->reg())) { // stack n_regs = lrg->scalable_reg_slots(); } for (int i = 1; i < n_regs; i++) { - lrg->insert(OptoReg::add(reg, -i)); + lrg->Insert(OptoReg::add(reg,-i)); } lrg->set_mask_size(n_regs); } else { // Else fatproj diff --git a/src/hotspot/share/opto/chaitin.hpp b/src/hotspot/share/opto/chaitin.hpp index b477c54fcae49..9b3f8123ac205 100644 --- a/src/hotspot/share/opto/chaitin.hpp +++ b/src/hotspot/share/opto/chaitin.hpp @@ -103,11 +103,11 @@ class LRG : public ResourceObj { private: RegMask _mask; // Allowed registers for this LRG - uint _mask_size; // cache of _mask.size(); + uint _mask_size; // cache of _mask.Size(); public: - int compute_mask_size() const { return _mask.is_infinite_stack() ? INFINITE_STACK_SIZE : _mask.size(); } + int compute_mask_size() const { return _mask.is_infinite_stack() ? INFINITE_STACK_SIZE : _mask.Size(); } void set_mask_size( int size ) { - assert((size == (int)INFINITE_STACK_SIZE) || (size == (int)_mask.size()), ""); + assert((size == (int)INFINITE_STACK_SIZE) || (size == (int)_mask.Size()), ""); _mask_size = size; #ifdef ASSERT _msize_valid=1; @@ -128,17 +128,17 @@ class LRG : public ResourceObj { // count of bits in the current mask. int get_invalid_mask_size() const { return _mask_size; } const RegMask &mask() const { return _mask; } - void set_mask(const RegMask& rm) { _mask.assignFrom(rm); DEBUG_ONLY(_msize_valid = 0;) } + void set_mask( const RegMask &rm ) { _mask = rm; DEBUG_ONLY(_msize_valid=0;)} void init_mask(Arena* arena) { new (&_mask) RegMask(arena); } - void and_with( const RegMask &rm ) { _mask.and_with(rm); DEBUG_ONLY(_msize_valid=0;)} - void subtract( const RegMask &rm ) { _mask.subtract(rm); DEBUG_ONLY(_msize_valid=0;)} - void subtract_inner(const RegMask& rm) { _mask.subtract_inner(rm); DEBUG_ONLY(_msize_valid = 0;) } - void clear() { _mask.clear() ; DEBUG_ONLY(_msize_valid=1); _mask_size = 0; } - void set_all() { _mask.set_all(); DEBUG_ONLY(_msize_valid = 1); _mask_size = _mask.rm_size_in_bits(); } + void AND( const RegMask &rm ) { _mask.AND(rm); DEBUG_ONLY(_msize_valid=0;)} + void SUBTRACT( const RegMask &rm ) { _mask.SUBTRACT(rm); DEBUG_ONLY(_msize_valid=0;)} + void SUBTRACT_inner(const RegMask& rm) { _mask.SUBTRACT_inner(rm); DEBUG_ONLY(_msize_valid = 0;) } + void Clear() { _mask.Clear() ; DEBUG_ONLY(_msize_valid=1); _mask_size = 0; } + void Set_All() { _mask.Set_All(); DEBUG_ONLY(_msize_valid = 1); _mask_size = _mask.rm_size_in_bits(); } bool rollover() { DEBUG_ONLY(_msize_valid = 1); _mask_size = _mask.rm_size_in_bits(); return _mask.rollover(); } - void insert( OptoReg::Name reg ) { _mask.insert(reg); DEBUG_ONLY(_msize_valid=0;) } - void remove( OptoReg::Name reg ) { _mask.remove(reg); DEBUG_ONLY(_msize_valid=0;) } + void Insert( OptoReg::Name reg ) { _mask.Insert(reg); DEBUG_ONLY(_msize_valid=0;) } + void Remove( OptoReg::Name reg ) { _mask.Remove(reg); DEBUG_ONLY(_msize_valid=0;) } void clear_to_sets() { _mask.clear_to_sets(_num_regs); DEBUG_ONLY(_msize_valid=0;) } private: @@ -624,7 +624,7 @@ class PhaseChaitin : public PhaseRegAlloc { void check_pressure_at_fatproj(uint fatproj_location, RegMask& fatproj_mask) { // this pressure is only valid at this instruction, i.e. we don't need to lower // the register pressure since the fat proj was never live before (going backwards) - uint new_pressure = current_pressure() + fatproj_mask.size(); + uint new_pressure = current_pressure() + fatproj_mask.Size(); if (new_pressure > final_pressure()) { _final_pressure = new_pressure; } diff --git a/src/hotspot/share/opto/coalesce.cpp b/src/hotspot/share/opto/coalesce.cpp index 82c1f7050c7fc..90a2dd0e152ec 100644 --- a/src/hotspot/share/opto/coalesce.cpp +++ b/src/hotspot/share/opto/coalesce.cpp @@ -118,7 +118,7 @@ void PhaseCoalesce::combine_these_two(Node *n1, Node *n2) { // Merge in the IFG _phc._ifg->Union( lr1, lr2 ); // Combine register restrictions - lrg1->and_with(lrg2->mask()); + lrg1->AND(lrg2->mask()); } } } @@ -503,8 +503,8 @@ void PhaseConservativeCoalesce::union_helper( Node *lr1_node, Node *lr2_node, ui lrgs(lr2).is_multidef() ) ? NodeSentinel : src_def; lrgs(lr2)._def = nullptr; // No def for lrg 2 - lrgs(lr2).clear(); // Force empty mask for LRG 2 - // lrgs(lr2)._size = 0; // Live-range 2 goes dead + lrgs(lr2).Clear(); // Force empty mask for LRG 2 + //lrgs(lr2)._size = 0; // Live-range 2 goes dead lrgs(lr1)._is_oop |= lrgs(lr2)._is_oop; lrgs(lr2)._is_oop = 0; // In particular, not an oop for GC info @@ -570,9 +570,9 @@ uint PhaseConservativeCoalesce::compute_separating_interferences(Node *dst_copy, // If we attempt to coalesce across a bound def if( lrgs(lidx).is_bound() ) { // Do not let the coalesced LRG expect to get the bound color - rm.subtract(lrgs(lidx).mask()); + rm.SUBTRACT( lrgs(lidx).mask() ); // Recompute rm_size - rm_size = rm.size(); + rm_size = rm.Size(); //if( rm._flags ) rm_size += 1000000; if( reg_degree >= rm_size ) return max_juint; } @@ -695,9 +695,9 @@ bool PhaseConservativeCoalesce::copy_copy(Node *dst_copy, Node *src_copy, Block // intersecting their allowed register sets. ResourceMark rm(C->regmask_arena()); RegMask mask(lrgs(lr1).mask(), C->regmask_arena()); - mask.and_with(lrgs(lr2).mask()); + mask.AND(lrgs(lr2).mask()); // Number of bits free - uint rm_size = mask.size(); + uint rm_size = mask.Size(); if (UseFPUForSpilling && mask.is_infinite_stack() ) { // Don't coalesce when frequency difference is large diff --git a/src/hotspot/share/opto/connode.hpp b/src/hotspot/share/opto/connode.hpp index 8cf3eea7570ea..4788858796015 100644 --- a/src/hotspot/share/opto/connode.hpp +++ b/src/hotspot/share/opto/connode.hpp @@ -43,8 +43,8 @@ class ConNode : public TypeNode { } virtual int Opcode() const; virtual uint hash() const; - virtual const RegMask& out_RegMask() const { return RegMask::EMPTY; } - virtual const RegMask& in_RegMask(uint) const { return RegMask::EMPTY; } + virtual const RegMask &out_RegMask() const { return RegMask::Empty; } + virtual const RegMask &in_RegMask(uint) const { return RegMask::Empty; } virtual Node* Ideal(PhaseGVN* phase, bool can_reshape) { return Node::Ideal(phase, can_reshape); diff --git a/src/hotspot/share/opto/divnode.cpp b/src/hotspot/share/opto/divnode.cpp index 06ba1856941a3..823745ea8e7fd 100644 --- a/src/hotspot/share/opto/divnode.cpp +++ b/src/hotspot/share/opto/divnode.cpp @@ -1668,10 +1668,10 @@ Node *DivModINode::match( const ProjNode *proj, const Matcher *match ) { uint ideal_reg = proj->ideal_reg(); RegMask rm; if (proj->_con == div_proj_num) { - rm.assignFrom(match->divI_proj_mask()); + rm = match->divI_proj_mask(); } else { assert(proj->_con == mod_proj_num, "must be div or mod projection"); - rm.assignFrom(match->modI_proj_mask()); + rm = match->modI_proj_mask(); } return new MachProjNode(this, proj->_con, rm, ideal_reg); } @@ -1683,10 +1683,10 @@ Node *DivModLNode::match( const ProjNode *proj, const Matcher *match ) { uint ideal_reg = proj->ideal_reg(); RegMask rm; if (proj->_con == div_proj_num) { - rm.assignFrom(match->divL_proj_mask()); + rm = match->divL_proj_mask(); } else { assert(proj->_con == mod_proj_num, "must be div or mod projection"); - rm.assignFrom(match->modL_proj_mask()); + rm = match->modL_proj_mask(); } return new MachProjNode(this, proj->_con, rm, ideal_reg); } @@ -1721,10 +1721,10 @@ Node* UDivModINode::match( const ProjNode *proj, const Matcher *match ) { uint ideal_reg = proj->ideal_reg(); RegMask rm; if (proj->_con == div_proj_num) { - rm.assignFrom(match->divI_proj_mask()); + rm = match->divI_proj_mask(); } else { assert(proj->_con == mod_proj_num, "must be div or mod projection"); - rm.assignFrom(match->modI_proj_mask()); + rm = match->modI_proj_mask(); } return new MachProjNode(this, proj->_con, rm, ideal_reg); } @@ -1736,10 +1736,10 @@ Node* UDivModLNode::match( const ProjNode *proj, const Matcher *match ) { uint ideal_reg = proj->ideal_reg(); RegMask rm; if (proj->_con == div_proj_num) { - rm.assignFrom(match->divL_proj_mask()); + rm = match->divL_proj_mask(); } else { assert(proj->_con == mod_proj_num, "must be div or mod projection"); - rm.assignFrom(match->modL_proj_mask()); + rm = match->modL_proj_mask(); } return new MachProjNode(this, proj->_con, rm, ideal_reg); } diff --git a/src/hotspot/share/opto/escape.cpp b/src/hotspot/share/opto/escape.cpp index a148b167ee301..cbf0666c00e4e 100644 --- a/src/hotspot/share/opto/escape.cpp +++ b/src/hotspot/share/opto/escape.cpp @@ -1296,8 +1296,9 @@ void ConnectionGraph::reduce_phi(PhiNode* ophi, GrowableArray &alloc_wo castpps.push(use); } else if (use->is_AddP() || use->is_Cmp()) { others.push(use); + } else if (use->is_SafePoint()) { + // processed later } else { - // Safepoints to be processed later; other users aren't expected here assert(use->is_SafePoint(), "Unexpected user of reducible Phi %d -> %d:%s:%d", ophi->_idx, use->_idx, use->Name(), use->outcnt()); } } diff --git a/src/hotspot/share/opto/gcm.cpp b/src/hotspot/share/opto/gcm.cpp index 4a1553b1e0092..72c001a64c473 100644 --- a/src/hotspot/share/opto/gcm.cpp +++ b/src/hotspot/share/opto/gcm.cpp @@ -1449,9 +1449,8 @@ Block* PhaseCFG::hoist_to_cheaper_block(Block* LCA, Block* early, Node* self) { // single register. Hoisting stretches the live range of the // single register and may force spilling. MachNode* mach = self->is_Mach() ? self->as_Mach() : nullptr; - if (mach != nullptr && mach->out_RegMask().is_bound1() && !mach->out_RegMask().is_empty()) { + if (mach != nullptr && mach->out_RegMask().is_bound1() && !mach->out_RegMask().is_Empty()) in_latency = true; - } #ifndef PRODUCT if (trace_opto_pipelining()) { diff --git a/src/hotspot/share/opto/ifg.cpp b/src/hotspot/share/opto/ifg.cpp index 1480e806f76a7..438209df8f823 100644 --- a/src/hotspot/share/opto/ifg.cpp +++ b/src/hotspot/share/opto/ifg.cpp @@ -55,7 +55,7 @@ void PhaseIFG::init( uint maxlrg ) { for( uint i = 0; i < maxlrg; i++ ) { _adjs[i].initialize(maxlrg); _lrgs[i].init_mask(_arena); - _lrgs[i].set_all(); + _lrgs[i].Set_All(); } } @@ -655,7 +655,7 @@ bool PhaseChaitin::remove_node_if_not_used(Block* b, uint location, Node* n, uin void PhaseChaitin::check_for_high_pressure_transition_at_fatproj(uint& block_reg_pressure, uint location, LRG& lrg, Pressure& pressure, const int op_regtype) { ResourceMark rm(C->regmask_arena()); RegMask mask_tmp(lrg.mask(), C->regmask_arena()); - mask_tmp.and_with(*Matcher::idealreg2regmask[op_regtype]); + mask_tmp.AND(*Matcher::idealreg2regmask[op_regtype]); pressure.check_pressure_at_fatproj(location, mask_tmp); } @@ -729,7 +729,7 @@ void PhaseChaitin::remove_bound_register_from_interfering_live_ranges(LRG& lrg, } // Remove bound register(s) from 'l's choices - old.assignFrom(interfering_lrg.mask()); + old = interfering_lrg.mask(); uint old_size = interfering_lrg.mask_size(); // Remove the bits from LRG 'mask' from LRG 'l' so 'l' no @@ -738,21 +738,21 @@ void PhaseChaitin::remove_bound_register_from_interfering_live_ranges(LRG& lrg, assert(!interfering_lrg._is_vector || !interfering_lrg._fat_proj, "sanity"); if (interfering_lrg.num_regs() > 1 && !interfering_lrg._fat_proj) { - r2mask.assignFrom(mask); + r2mask = mask; // Leave only aligned set of bits. r2mask.smear_to_sets(interfering_lrg.num_regs()); // It includes vector case. - interfering_lrg.subtract(r2mask); + interfering_lrg.SUBTRACT(r2mask); interfering_lrg.compute_set_mask_size(); } else if (r_size != 1) { // fat proj - interfering_lrg.subtract(mask); + interfering_lrg.SUBTRACT(mask); interfering_lrg.compute_set_mask_size(); } else { // Common case: size 1 bound removal OptoReg::Name r_reg = mask.find_first_elem(); - if (interfering_lrg.mask().member(r_reg)) { - interfering_lrg.remove(r_reg); + if (interfering_lrg.mask().Member(r_reg)) { + interfering_lrg.Remove(r_reg); interfering_lrg.set_mask_size(interfering_lrg.mask().is_infinite_stack() ? LRG::INFINITE_STACK_SIZE : old_size - 1); } } @@ -933,7 +933,7 @@ uint PhaseChaitin::build_ifg_physical( ResourceArea *a ) { // Since rematerializable DEFs are not bound but the live range is, // some uses must be bound. If we spill live range 'r', it can // rematerialize at each use site according to its bindings. - if (lrg.is_bound() && !n->rematerialize() && !lrg.mask().is_empty()) { + if (lrg.is_bound() && !n->rematerialize() && !lrg.mask().is_Empty()) { remove_bound_register_from_interfering_live_ranges(lrg, &liveout, must_spill); } interfere_with_live(lid, &liveout); diff --git a/src/hotspot/share/opto/ifnode.cpp b/src/hotspot/share/opto/ifnode.cpp index 83e975b95a26e..b397c2c5852e4 100644 --- a/src/hotspot/share/opto/ifnode.cpp +++ b/src/hotspot/share/opto/ifnode.cpp @@ -82,7 +82,7 @@ const Type* IfNode::Value(PhaseGVN* phase) const { } const RegMask &IfNode::out_RegMask() const { - return RegMask::EMPTY; + return RegMask::Empty; } //------------------------------split_if--------------------------------------- diff --git a/src/hotspot/share/opto/lcm.cpp b/src/hotspot/share/opto/lcm.cpp index 53a503866fac1..fd7644f858760 100644 --- a/src/hotspot/share/opto/lcm.cpp +++ b/src/hotspot/share/opto/lcm.cpp @@ -855,12 +855,12 @@ void PhaseCFG::needed_for_next_call(Block* block, Node* this_call, VectorSet& ne static void add_call_kills(MachProjNode *proj, RegMask& regs, const char* save_policy, bool exclude_soe) { // Fill in the kill mask for the call for( OptoReg::Name r = OptoReg::Name(0); r < _last_Mach_Reg; r=OptoReg::add(r,1) ) { - if (!regs.member(r)) { // Not already defined by the call + if( !regs.Member(r) ) { // Not already defined by the call // Save-on-call register? if ((save_policy[r] == 'C') || (save_policy[r] == 'A') || ((save_policy[r] == 'E') && exclude_soe)) { - proj->_rout.insert(r); + proj->_rout.Insert(r); } } } @@ -884,7 +884,7 @@ uint PhaseCFG::sched_call(Block* block, uint node_cnt, Node_List& worklist, Grow // Schedule next to call block->map_node(n, node_cnt++); // Collect defined registers - regs.or_with(n->out_RegMask()); + regs.OR(n->out_RegMask()); // Check for scheduling the next control-definer if( n->bottom_type() == Type::CONTROL ) // Warm up next pile of heuristic bits @@ -907,12 +907,12 @@ uint PhaseCFG::sched_call(Block* block, uint node_cnt, Node_List& worklist, Grow // Act as if the call defines the Frame Pointer. // Certainly the FP is alive and well after the call. - regs.insert(_matcher.c_frame_pointer()); + regs.Insert(_matcher.c_frame_pointer()); // Set all registers killed and not already defined by the call. uint r_cnt = mcall->tf()->range()->cnt(); int op = mcall->ideal_Opcode(); - MachProjNode* proj = new MachProjNode(mcall, r_cnt + 1, RegMask::EMPTY, MachProjNode::fat_proj); + MachProjNode *proj = new MachProjNode( mcall, r_cnt+1, RegMask::Empty, MachProjNode::fat_proj ); map_node_to_block(proj, block); block->insert_node(proj, node_cnt++); @@ -1164,10 +1164,10 @@ bool PhaseCFG::schedule_local(Block* block, GrowableArray& ready_cnt, Vecto if (n->is_Mach() && n->as_Mach()->has_call()) { RegMask regs; - regs.insert(_matcher.c_frame_pointer()); - regs.or_with(n->out_RegMask()); + regs.Insert(_matcher.c_frame_pointer()); + regs.OR(n->out_RegMask()); - MachProjNode* proj = new MachProjNode(n, 1, RegMask::EMPTY, MachProjNode::fat_proj); + MachProjNode *proj = new MachProjNode( n, 1, RegMask::Empty, MachProjNode::fat_proj ); map_node_to_block(proj, block); block->insert_node(proj, phi_cnt++); diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index bd8a550b9ab76..ee3a3d3ba47bd 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -7273,7 +7273,7 @@ bool LibraryCallKit::inline_cipherBlockChaining_AESCrypt(vmIntrinsics::ID id) { const TypeInstPtr* tinst = _gvn.type(cipherBlockChaining_object)->isa_instptr(); assert(tinst != nullptr, "CBC obj is null"); assert(tinst->is_loaded(), "CBC obj is not loaded"); - ciKlass* klass_AESCrypt = tinst->instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AES_Crypt")); + ciKlass* klass_AESCrypt = tinst->instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt")); assert(klass_AESCrypt->is_loaded(), "predicate checks that this class is loaded"); ciInstanceKlass* instklass_AESCrypt = klass_AESCrypt->as_instance_klass(); @@ -7359,7 +7359,7 @@ bool LibraryCallKit::inline_electronicCodeBook_AESCrypt(vmIntrinsics::ID id) { const TypeInstPtr* tinst = _gvn.type(electronicCodeBook_object)->isa_instptr(); assert(tinst != nullptr, "ECB obj is null"); assert(tinst->is_loaded(), "ECB obj is not loaded"); - ciKlass* klass_AESCrypt = tinst->instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AES_Crypt")); + ciKlass* klass_AESCrypt = tinst->instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt")); assert(klass_AESCrypt->is_loaded(), "predicate checks that this class is loaded"); ciInstanceKlass* instklass_AESCrypt = klass_AESCrypt->as_instance_klass(); @@ -7429,7 +7429,7 @@ bool LibraryCallKit::inline_counterMode_AESCrypt(vmIntrinsics::ID id) { const TypeInstPtr* tinst = _gvn.type(counterMode_object)->isa_instptr(); assert(tinst != nullptr, "CTR obj is null"); assert(tinst->is_loaded(), "CTR obj is not loaded"); - ciKlass* klass_AESCrypt = tinst->instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AES_Crypt")); + ciKlass* klass_AESCrypt = tinst->instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt")); assert(klass_AESCrypt->is_loaded(), "predicate checks that this class is loaded"); ciInstanceKlass* instklass_AESCrypt = klass_AESCrypt->as_instance_klass(); const TypeKlassPtr* aklass = TypeKlassPtr::make(instklass_AESCrypt); @@ -7469,7 +7469,7 @@ Node * LibraryCallKit::get_key_start_from_aescrypt_object(Node *aescrypt_object) // However, ppc64 vncipher processes MixColumns and requires the same round keys with encryption. // The ppc64 and riscv64 stubs of encryption and decryption use the same round keys (sessionK[0]). Node* objSessionK = load_field_from_object(aescrypt_object, "sessionK", "[[I"); - assert (objSessionK != nullptr, "wrong version of com.sun.crypto.provider.AES_Crypt"); + assert (objSessionK != nullptr, "wrong version of com.sun.crypto.provider.AESCrypt"); if (objSessionK == nullptr) { return (Node *) nullptr; } @@ -7477,7 +7477,7 @@ Node * LibraryCallKit::get_key_start_from_aescrypt_object(Node *aescrypt_object) #else Node* objAESCryptKey = load_field_from_object(aescrypt_object, "K", "[I"); #endif // PPC64 - assert (objAESCryptKey != nullptr, "wrong version of com.sun.crypto.provider.AES_Crypt"); + assert (objAESCryptKey != nullptr, "wrong version of com.sun.crypto.provider.AESCrypt"); if (objAESCryptKey == nullptr) return (Node *) nullptr; // now have the array, need to get the start address of the K array @@ -7512,7 +7512,7 @@ Node* LibraryCallKit::inline_cipherBlockChaining_AESCrypt_predicate(bool decrypt assert(tinst->is_loaded(), "CBCobj is not loaded"); // we want to do an instanceof comparison against the AESCrypt class - ciKlass* klass_AESCrypt = tinst->instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AES_Crypt")); + ciKlass* klass_AESCrypt = tinst->instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt")); if (!klass_AESCrypt->is_loaded()) { // if AESCrypt is not even loaded, we never take the intrinsic fast path Node* ctrl = control(); @@ -7575,7 +7575,7 @@ Node* LibraryCallKit::inline_electronicCodeBook_AESCrypt_predicate(bool decrypti assert(tinst->is_loaded(), "ECBobj is not loaded"); // we want to do an instanceof comparison against the AESCrypt class - ciKlass* klass_AESCrypt = tinst->instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AES_Crypt")); + ciKlass* klass_AESCrypt = tinst->instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt")); if (!klass_AESCrypt->is_loaded()) { // if AESCrypt is not even loaded, we never take the intrinsic fast path Node* ctrl = control(); @@ -7635,7 +7635,7 @@ Node* LibraryCallKit::inline_counterMode_AESCrypt_predicate() { assert(tinst->is_loaded(), "CTRobj is not loaded"); // we want to do an instanceof comparison against the AESCrypt class - ciKlass* klass_AESCrypt = tinst->instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AES_Crypt")); + ciKlass* klass_AESCrypt = tinst->instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt")); if (!klass_AESCrypt->is_loaded()) { // if AESCrypt is not even loaded, we never take the intrinsic fast path Node* ctrl = control(); @@ -8608,7 +8608,7 @@ bool LibraryCallKit::inline_galoisCounterMode_AESCrypt() { const TypeInstPtr* tinst = _gvn.type(gctr_object)->isa_instptr(); assert(tinst != nullptr, "GCTR obj is null"); assert(tinst->is_loaded(), "GCTR obj is not loaded"); - ciKlass* klass_AESCrypt = tinst->instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AES_Crypt")); + ciKlass* klass_AESCrypt = tinst->instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt")); assert(klass_AESCrypt->is_loaded(), "predicate checks that this class is loaded"); ciInstanceKlass* instklass_AESCrypt = klass_AESCrypt->as_instance_klass(); const TypeKlassPtr* aklass = TypeKlassPtr::make(instklass_AESCrypt); @@ -8662,7 +8662,7 @@ Node* LibraryCallKit::inline_galoisCounterMode_AESCrypt_predicate() { assert(tinst->is_loaded(), "GCTR obj is not loaded"); // we want to do an instanceof comparison against the AESCrypt class - ciKlass* klass_AESCrypt = tinst->instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AES_Crypt")); + ciKlass* klass_AESCrypt = tinst->instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt")); if (!klass_AESCrypt->is_loaded()) { // if AESCrypt is not even loaded, we never take the intrinsic fast path Node* ctrl = control(); diff --git a/src/hotspot/share/opto/loopUnswitch.cpp b/src/hotspot/share/opto/loopUnswitch.cpp index f79afee31039c..b40a0492df511 100644 --- a/src/hotspot/share/opto/loopUnswitch.cpp +++ b/src/hotspot/share/opto/loopUnswitch.cpp @@ -522,9 +522,7 @@ IfTrueNode* PhaseIdealLoop::create_new_if_for_multiversion(IfTrueNode* multivers // Hook region into slow_path, in stead of the multiversion_slow_proj. // This also moves all other dependencies of the multiversion_slow_proj to the region. - // The lazy_replace ensures that any get_ctrl that used to have multiversion_slow_proj - // as their control are forwarded to the new region node as their control. - lazy_replace(multiversion_slow_proj, region); + _igvn.replace_node(multiversion_slow_proj, region); return new_if_true; } diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp index e8058edb4e5e5..4cb1862cbb939 100644 --- a/src/hotspot/share/opto/loopnode.cpp +++ b/src/hotspot/share/opto/loopnode.cpp @@ -5176,20 +5176,21 @@ void PhaseIdealLoop::build_and_optimize() { continue; } Node* head = lpt->_head; - if (!lpt->is_innermost()) continue; + if (!head->is_BaseCountedLoop() || !lpt->is_innermost()) continue; // check for vectorized loops, any reassociation of invariants was already done - if (head->is_CountedLoop() && head->as_CountedLoop()->is_unroll_only()) { - continue; - } else { - AutoNodeBudget node_budget(this); - lpt->reassociate_invariants(this); + if (head->is_CountedLoop()) { + if (head->as_CountedLoop()->is_unroll_only()) { + continue; + } else { + AutoNodeBudget node_budget(this); + lpt->reassociate_invariants(this); + } } // Because RCE opportunities can be masked by split_thru_phi, // look for RCE candidates and inhibit split_thru_phi // on just their loop-phi's for this pass of loop opts if (SplitIfBlocks && do_split_ifs && - head->is_BaseCountedLoop() && head->as_BaseCountedLoop()->is_valid_counted_loop(head->as_BaseCountedLoop()->bt()) && (lpt->policy_range_check(this, true, T_LONG) || (head->is_CountedLoop() && lpt->policy_range_check(this, true, T_INT)))) { diff --git a/src/hotspot/share/opto/machnode.cpp b/src/hotspot/share/opto/machnode.cpp index e58befd8032d8..5da929e474860 100644 --- a/src/hotspot/share/opto/machnode.cpp +++ b/src/hotspot/share/opto/machnode.cpp @@ -525,7 +525,7 @@ bool MachNode::rematerialize() const { uint idx = oper_input_base(); if (req() > idx) { const RegMask &rm = in_RegMask(idx); - if (!rm.is_empty() && rm.is_bound(ideal_reg())) { + if (!rm.is_Empty() && rm.is_bound(ideal_reg())) { return false; } } @@ -619,11 +619,8 @@ void MachNullCheckNode::save_label( Label** label, uint* block_num ) { } const RegMask &MachNullCheckNode::in_RegMask( uint idx ) const { - if (idx == 0) { - return RegMask::EMPTY; - } else { - return in(1)->as_Mach()->out_RegMask(); - } + if( idx == 0 ) return RegMask::Empty; + else return in(1)->as_Mach()->out_RegMask(); } //============================================================================= diff --git a/src/hotspot/share/opto/machnode.hpp b/src/hotspot/share/opto/machnode.hpp index 30ac9181beccf..43e9a35df34b4 100644 --- a/src/hotspot/share/opto/machnode.hpp +++ b/src/hotspot/share/opto/machnode.hpp @@ -737,7 +737,7 @@ class MachNullCheckNode : public MachBranchNode { virtual const class Type *bottom_type() const { return TypeTuple::IFBOTH; } virtual uint ideal_reg() const { return NotAMachineReg; } virtual const RegMask &in_RegMask(uint) const; - virtual const RegMask& out_RegMask() const { return RegMask::EMPTY; } + virtual const RegMask &out_RegMask() const { return RegMask::Empty; } #ifndef PRODUCT virtual const char *Name() const { return "NullCheck"; } virtual void format( PhaseRegAlloc *, outputStream *st ) const; @@ -769,7 +769,7 @@ class MachProjNode : public ProjNode { virtual int Opcode() const; virtual const Type *bottom_type() const; virtual const TypePtr *adr_type() const; - virtual const RegMask& in_RegMask(uint) const { return RegMask::EMPTY; } + virtual const RegMask &in_RegMask(uint) const { return RegMask::Empty; } virtual const RegMask &out_RegMask() const { return _rout; } virtual uint ideal_reg() const { return _ideal_reg; } // Need size_of() for virtual ProjNode::clone() diff --git a/src/hotspot/share/opto/matcher.cpp b/src/hotspot/share/opto/matcher.cpp index c63cefe7ac201..7d73487cf8840 100644 --- a/src/hotspot/share/opto/matcher.cpp +++ b/src/hotspot/share/opto/matcher.cpp @@ -176,12 +176,12 @@ void Matcher::match( ) { if (C->failing()) { return; } - assert(_return_addr_mask.is_empty(), + assert(_return_addr_mask.is_Empty(), "return address mask must be empty initially"); - _return_addr_mask.insert(return_addr()); + _return_addr_mask.Insert(return_addr()); #ifdef _LP64 // Pointers take 2 slots in 64-bit land - _return_addr_mask.insert(OptoReg::add(return_addr(), 1)); + _return_addr_mask.Insert(OptoReg::add(return_addr(),1)); #endif // Map a Java-signature return type into return register-value @@ -195,9 +195,9 @@ void Matcher::match( ) { OptoRegPair regs = return_value(ireg); // And mask for same - _return_value_mask.assignFrom(RegMask(regs.first())); + _return_value_mask = RegMask(regs.first()); if( OptoReg::is_valid(regs.second()) ) - _return_value_mask.insert(regs.second()); + _return_value_mask.Insert(regs.second()); } // --------------- @@ -261,7 +261,7 @@ void Matcher::match( ) { assert( is_even(_in_arg_limit), "out_preserve must be even" ); for( i = 0; i < argcnt; i++ ) { // Permit args to have no register - _calling_convention_mask[i].clear(); + _calling_convention_mask[i].Clear(); if( !vm_parm_regs[i].first()->is_valid() && !vm_parm_regs[i].second()->is_valid() ) { _parm_regs[i].set_bad(); continue; @@ -273,11 +273,11 @@ void Matcher::match( ) { OptoReg::Name reg1 = warp_incoming_stk_arg(vm_parm_regs[i].first()); if( OptoReg::is_valid(reg1)) - _calling_convention_mask[i].insert(reg1); + _calling_convention_mask[i].Insert(reg1); OptoReg::Name reg2 = warp_incoming_stk_arg(vm_parm_regs[i].second()); if( OptoReg::is_valid(reg2)) - _calling_convention_mask[i].insert(reg2); + _calling_convention_mask[i].Insert(reg2); // Saved biased stack-slot register number _parm_regs[i].set_pair(reg2, reg1); @@ -422,11 +422,11 @@ static RegMask *init_input_masks( uint size, RegMask &ret_adr, RegMask &fp ) { new (rms + i) RegMask(Compile::current()->comp_arena()); } // Do all the pre-defined register masks - rms[TypeFunc::Control ].assignFrom(RegMask::EMPTY); - rms[TypeFunc::I_O ].assignFrom(RegMask::EMPTY); - rms[TypeFunc::Memory ].assignFrom(RegMask::EMPTY); - rms[TypeFunc::ReturnAdr].assignFrom(ret_adr); - rms[TypeFunc::FramePtr ].assignFrom(fp); + rms[TypeFunc::Control ] = RegMask::Empty; + rms[TypeFunc::I_O ] = RegMask::Empty; + rms[TypeFunc::Memory ] = RegMask::Empty; + rms[TypeFunc::ReturnAdr] = ret_adr; + rms[TypeFunc::FramePtr ] = fp; return rms; } @@ -471,15 +471,15 @@ void Matcher::init_first_stack_mask() { assert(index == NOF_STACK_MASKS, "wrong size"); // At first, start with the empty mask - C->FIRST_STACK_mask().clear(); + C->FIRST_STACK_mask().Clear(); // Add in the incoming argument area OptoReg::Name init_in = OptoReg::add(_old_SP, C->out_preserve_stack_slots()); for (OptoReg::Name i = init_in; i < _in_arg_limit; i = OptoReg::add(i, 1)) { - C->FIRST_STACK_mask().insert(i); + C->FIRST_STACK_mask().Insert(i); } // Add in all bits past the outgoing argument area - C->FIRST_STACK_mask().set_all_from(_out_arg_limit); + C->FIRST_STACK_mask().Set_All_From(_out_arg_limit); // Make spill masks. Registers for their class, plus FIRST_STACK_mask. RegMask aligned_stack_mask(C->FIRST_STACK_mask(), C->comp_arena()); @@ -488,44 +488,44 @@ void Matcher::init_first_stack_mask() { assert(aligned_stack_mask.is_infinite_stack(), "should be infinite stack"); RegMask scalable_stack_mask(aligned_stack_mask, C->comp_arena()); - idealreg2spillmask[Op_RegP]->assignFrom(*idealreg2regmask[Op_RegP]); + *idealreg2spillmask[Op_RegP] = *idealreg2regmask[Op_RegP]; #ifdef _LP64 - idealreg2spillmask[Op_RegN]->assignFrom(*idealreg2regmask[Op_RegN]); - idealreg2spillmask[Op_RegN]->or_with(C->FIRST_STACK_mask()); - idealreg2spillmask[Op_RegP]->or_with(aligned_stack_mask); + *idealreg2spillmask[Op_RegN] = *idealreg2regmask[Op_RegN]; + idealreg2spillmask[Op_RegN]->OR(C->FIRST_STACK_mask()); + idealreg2spillmask[Op_RegP]->OR(aligned_stack_mask); #else - idealreg2spillmask[Op_RegP]->or_with(C->FIRST_STACK_mask()); + idealreg2spillmask[Op_RegP]->OR(C->FIRST_STACK_mask()); #endif - idealreg2spillmask[Op_RegI]->assignFrom(*idealreg2regmask[Op_RegI]); - idealreg2spillmask[Op_RegI]->or_with(C->FIRST_STACK_mask()); - idealreg2spillmask[Op_RegL]->assignFrom(*idealreg2regmask[Op_RegL]); - idealreg2spillmask[Op_RegL]->or_with(aligned_stack_mask); - idealreg2spillmask[Op_RegF]->assignFrom(*idealreg2regmask[Op_RegF]); - idealreg2spillmask[Op_RegF]->or_with(C->FIRST_STACK_mask()); - idealreg2spillmask[Op_RegD]->assignFrom(*idealreg2regmask[Op_RegD]); - idealreg2spillmask[Op_RegD]->or_with(aligned_stack_mask); + *idealreg2spillmask[Op_RegI] = *idealreg2regmask[Op_RegI]; + idealreg2spillmask[Op_RegI]->OR(C->FIRST_STACK_mask()); + *idealreg2spillmask[Op_RegL] = *idealreg2regmask[Op_RegL]; + idealreg2spillmask[Op_RegL]->OR(aligned_stack_mask); + *idealreg2spillmask[Op_RegF] = *idealreg2regmask[Op_RegF]; + idealreg2spillmask[Op_RegF]->OR(C->FIRST_STACK_mask()); + *idealreg2spillmask[Op_RegD] = *idealreg2regmask[Op_RegD]; + idealreg2spillmask[Op_RegD]->OR(aligned_stack_mask); if (Matcher::has_predicated_vectors()) { - idealreg2spillmask[Op_RegVectMask]->assignFrom(*idealreg2regmask[Op_RegVectMask]); - idealreg2spillmask[Op_RegVectMask]->or_with(aligned_stack_mask); + *idealreg2spillmask[Op_RegVectMask] = *idealreg2regmask[Op_RegVectMask]; + idealreg2spillmask[Op_RegVectMask]->OR(aligned_stack_mask); } else { - idealreg2spillmask[Op_RegVectMask]->assignFrom(RegMask::EMPTY); + *idealreg2spillmask[Op_RegVectMask] = RegMask::Empty; } if (Matcher::vector_size_supported(T_BYTE,4)) { - idealreg2spillmask[Op_VecS]->assignFrom(*idealreg2regmask[Op_VecS]); - idealreg2spillmask[Op_VecS]->or_with(C->FIRST_STACK_mask()); + *idealreg2spillmask[Op_VecS] = *idealreg2regmask[Op_VecS]; + idealreg2spillmask[Op_VecS]->OR(C->FIRST_STACK_mask()); } else { - idealreg2spillmask[Op_VecS]->assignFrom(RegMask::EMPTY); + *idealreg2spillmask[Op_VecS] = RegMask::Empty; } if (Matcher::vector_size_supported(T_FLOAT,2)) { // For VecD we need dual alignment and 8 bytes (2 slots) for spills. // RA guarantees such alignment since it is needed for Double and Long values. - idealreg2spillmask[Op_VecD]->assignFrom(*idealreg2regmask[Op_VecD]); - idealreg2spillmask[Op_VecD]->or_with(aligned_stack_mask); + *idealreg2spillmask[Op_VecD] = *idealreg2regmask[Op_VecD]; + idealreg2spillmask[Op_VecD]->OR(aligned_stack_mask); } else { - idealreg2spillmask[Op_VecD]->assignFrom(RegMask::EMPTY); + *idealreg2spillmask[Op_VecD] = RegMask::Empty; } if (Matcher::vector_size_supported(T_FLOAT,4)) { @@ -538,45 +538,45 @@ void Matcher::init_first_stack_mask() { // otherwise vector spills could stomp over stack slots in caller frame. OptoReg::Name in = OptoReg::add(_in_arg_limit, -1); for (int k = 1; (in >= init_in) && (k < RegMask::SlotsPerVecX); k++) { - aligned_stack_mask.remove(in); + aligned_stack_mask.Remove(in); in = OptoReg::add(in, -1); } - aligned_stack_mask.clear_to_sets(RegMask::SlotsPerVecX); - assert(aligned_stack_mask.is_infinite_stack(), "should be infinite stack"); - idealreg2spillmask[Op_VecX]->assignFrom(*idealreg2regmask[Op_VecX]); - idealreg2spillmask[Op_VecX]->or_with(aligned_stack_mask); + aligned_stack_mask.clear_to_sets(RegMask::SlotsPerVecX); + assert(aligned_stack_mask.is_infinite_stack(), "should be infinite stack"); + *idealreg2spillmask[Op_VecX] = *idealreg2regmask[Op_VecX]; + idealreg2spillmask[Op_VecX]->OR(aligned_stack_mask); } else { - idealreg2spillmask[Op_VecX]->assignFrom(RegMask::EMPTY); + *idealreg2spillmask[Op_VecX] = RegMask::Empty; } if (Matcher::vector_size_supported(T_FLOAT,8)) { // For VecY we need octo alignment and 32 bytes (8 slots) for spills. OptoReg::Name in = OptoReg::add(_in_arg_limit, -1); for (int k = 1; (in >= init_in) && (k < RegMask::SlotsPerVecY); k++) { - aligned_stack_mask.remove(in); + aligned_stack_mask.Remove(in); in = OptoReg::add(in, -1); } - aligned_stack_mask.clear_to_sets(RegMask::SlotsPerVecY); - assert(aligned_stack_mask.is_infinite_stack(), "should be infinite stack"); - idealreg2spillmask[Op_VecY]->assignFrom(*idealreg2regmask[Op_VecY]); - idealreg2spillmask[Op_VecY]->or_with(aligned_stack_mask); + aligned_stack_mask.clear_to_sets(RegMask::SlotsPerVecY); + assert(aligned_stack_mask.is_infinite_stack(), "should be infinite stack"); + *idealreg2spillmask[Op_VecY] = *idealreg2regmask[Op_VecY]; + idealreg2spillmask[Op_VecY]->OR(aligned_stack_mask); } else { - idealreg2spillmask[Op_VecY]->assignFrom(RegMask::EMPTY); + *idealreg2spillmask[Op_VecY] = RegMask::Empty; } if (Matcher::vector_size_supported(T_FLOAT,16)) { // For VecZ we need enough alignment and 64 bytes (16 slots) for spills. OptoReg::Name in = OptoReg::add(_in_arg_limit, -1); for (int k = 1; (in >= init_in) && (k < RegMask::SlotsPerVecZ); k++) { - aligned_stack_mask.remove(in); + aligned_stack_mask.Remove(in); in = OptoReg::add(in, -1); } - aligned_stack_mask.clear_to_sets(RegMask::SlotsPerVecZ); - assert(aligned_stack_mask.is_infinite_stack(), "should be infinite stack"); - idealreg2spillmask[Op_VecZ]->assignFrom(*idealreg2regmask[Op_VecZ]); - idealreg2spillmask[Op_VecZ]->or_with(aligned_stack_mask); + aligned_stack_mask.clear_to_sets(RegMask::SlotsPerVecZ); + assert(aligned_stack_mask.is_infinite_stack(), "should be infinite stack"); + *idealreg2spillmask[Op_VecZ] = *idealreg2regmask[Op_VecZ]; + idealreg2spillmask[Op_VecZ]->OR(aligned_stack_mask); } else { - idealreg2spillmask[Op_VecZ]->assignFrom(RegMask::EMPTY); + *idealreg2spillmask[Op_VecZ] = RegMask::Empty; } if (Matcher::supports_scalable_vector()) { @@ -586,31 +586,31 @@ void Matcher::init_first_stack_mask() { // Exclude last input arg stack slots to avoid spilling vector register there, // otherwise RegVectMask spills could stomp over stack slots in caller frame. for (; (in >= init_in) && (k < scalable_predicate_reg_slots()); k++) { - scalable_stack_mask.remove(in); + scalable_stack_mask.Remove(in); in = OptoReg::add(in, -1); } // For RegVectMask scalable_stack_mask.clear_to_sets(scalable_predicate_reg_slots()); assert(scalable_stack_mask.is_infinite_stack(), "should be infinite stack"); - idealreg2spillmask[Op_RegVectMask]->assignFrom(*idealreg2regmask[Op_RegVectMask]); - idealreg2spillmask[Op_RegVectMask]->or_with(scalable_stack_mask); + *idealreg2spillmask[Op_RegVectMask] = *idealreg2regmask[Op_RegVectMask]; + idealreg2spillmask[Op_RegVectMask]->OR(scalable_stack_mask); } // Exclude last input arg stack slots to avoid spilling vector register there, // otherwise vector spills could stomp over stack slots in caller frame. for (; (in >= init_in) && (k < scalable_vector_reg_size(T_FLOAT)); k++) { - scalable_stack_mask.remove(in); + scalable_stack_mask.Remove(in); in = OptoReg::add(in, -1); } // For VecA - scalable_stack_mask.clear_to_sets(RegMask::SlotsPerVecA); - assert(scalable_stack_mask.is_infinite_stack(), "should be infinite stack"); - idealreg2spillmask[Op_VecA]->assignFrom(*idealreg2regmask[Op_VecA]); - idealreg2spillmask[Op_VecA]->or_with(scalable_stack_mask); + scalable_stack_mask.clear_to_sets(RegMask::SlotsPerVecA); + assert(scalable_stack_mask.is_infinite_stack(), "should be infinite stack"); + *idealreg2spillmask[Op_VecA] = *idealreg2regmask[Op_VecA]; + idealreg2spillmask[Op_VecA]->OR(scalable_stack_mask); } else { - idealreg2spillmask[Op_VecA]->assignFrom(RegMask::EMPTY); + *idealreg2spillmask[Op_VecA] = RegMask::Empty; } if (UseFPUForSpilling) { @@ -618,20 +618,20 @@ void Matcher::init_first_stack_mask() { // symmetric and that the registers involved are the same size. // On sparc for instance we may have to use 64 bit moves will // kill 2 registers when used with F0-F31. - idealreg2spillmask[Op_RegI]->or_with(*idealreg2regmask[Op_RegF]); - idealreg2spillmask[Op_RegF]->or_with(*idealreg2regmask[Op_RegI]); + idealreg2spillmask[Op_RegI]->OR(*idealreg2regmask[Op_RegF]); + idealreg2spillmask[Op_RegF]->OR(*idealreg2regmask[Op_RegI]); #ifdef _LP64 - idealreg2spillmask[Op_RegN]->or_with(*idealreg2regmask[Op_RegF]); - idealreg2spillmask[Op_RegL]->or_with(*idealreg2regmask[Op_RegD]); - idealreg2spillmask[Op_RegD]->or_with(*idealreg2regmask[Op_RegL]); - idealreg2spillmask[Op_RegP]->or_with(*idealreg2regmask[Op_RegD]); + idealreg2spillmask[Op_RegN]->OR(*idealreg2regmask[Op_RegF]); + idealreg2spillmask[Op_RegL]->OR(*idealreg2regmask[Op_RegD]); + idealreg2spillmask[Op_RegD]->OR(*idealreg2regmask[Op_RegL]); + idealreg2spillmask[Op_RegP]->OR(*idealreg2regmask[Op_RegD]); #else - idealreg2spillmask[Op_RegP]->or_with(*idealreg2regmask[Op_RegF]); + idealreg2spillmask[Op_RegP]->OR(*idealreg2regmask[Op_RegF]); #ifdef ARM // ARM has support for moving 64bit values between a pair of // integer registers and a double register - idealreg2spillmask[Op_RegL]->or_with(*idealreg2regmask[Op_RegD]); - idealreg2spillmask[Op_RegD]->or_with(*idealreg2regmask[Op_RegL]); + idealreg2spillmask[Op_RegL]->OR(*idealreg2regmask[Op_RegD]); + idealreg2spillmask[Op_RegD]->OR(*idealreg2regmask[Op_RegL]); #endif #endif } @@ -639,40 +639,40 @@ void Matcher::init_first_stack_mask() { // Make up debug masks. Any spill slot plus callee-save (SOE) registers. // Caller-save (SOC, AS) registers are assumed to be trashable by the various // inline-cache fixup routines. - idealreg2debugmask[Op_RegN]->assignFrom(*idealreg2spillmask[Op_RegN]); - idealreg2debugmask[Op_RegI]->assignFrom(*idealreg2spillmask[Op_RegI]); - idealreg2debugmask[Op_RegL]->assignFrom(*idealreg2spillmask[Op_RegL]); - idealreg2debugmask[Op_RegF]->assignFrom(*idealreg2spillmask[Op_RegF]); - idealreg2debugmask[Op_RegD]->assignFrom(*idealreg2spillmask[Op_RegD]); - idealreg2debugmask[Op_RegP]->assignFrom(*idealreg2spillmask[Op_RegP]); - idealreg2debugmask[Op_RegVectMask]->assignFrom(*idealreg2spillmask[Op_RegVectMask]); - - idealreg2debugmask[Op_VecA]->assignFrom(*idealreg2spillmask[Op_VecA]); - idealreg2debugmask[Op_VecS]->assignFrom(*idealreg2spillmask[Op_VecS]); - idealreg2debugmask[Op_VecD]->assignFrom(*idealreg2spillmask[Op_VecD]); - idealreg2debugmask[Op_VecX]->assignFrom(*idealreg2spillmask[Op_VecX]); - idealreg2debugmask[Op_VecY]->assignFrom(*idealreg2spillmask[Op_VecY]); - idealreg2debugmask[Op_VecZ]->assignFrom(*idealreg2spillmask[Op_VecZ]); + *idealreg2debugmask [Op_RegN] = *idealreg2spillmask[Op_RegN]; + *idealreg2debugmask [Op_RegI] = *idealreg2spillmask[Op_RegI]; + *idealreg2debugmask [Op_RegL] = *idealreg2spillmask[Op_RegL]; + *idealreg2debugmask [Op_RegF] = *idealreg2spillmask[Op_RegF]; + *idealreg2debugmask [Op_RegD] = *idealreg2spillmask[Op_RegD]; + *idealreg2debugmask [Op_RegP] = *idealreg2spillmask[Op_RegP]; + *idealreg2debugmask [Op_RegVectMask] = *idealreg2spillmask[Op_RegVectMask]; + + *idealreg2debugmask [Op_VecA] = *idealreg2spillmask[Op_VecA]; + *idealreg2debugmask [Op_VecS] = *idealreg2spillmask[Op_VecS]; + *idealreg2debugmask [Op_VecD] = *idealreg2spillmask[Op_VecD]; + *idealreg2debugmask [Op_VecX] = *idealreg2spillmask[Op_VecX]; + *idealreg2debugmask [Op_VecY] = *idealreg2spillmask[Op_VecY]; + *idealreg2debugmask [Op_VecZ] = *idealreg2spillmask[Op_VecZ]; // Prevent stub compilations from attempting to reference // callee-saved (SOE) registers from debug info bool exclude_soe = !Compile::current()->is_method_compilation(); RegMask* caller_save_mask = exclude_soe ? &caller_save_regmask_exclude_soe : &caller_save_regmask; - idealreg2debugmask[Op_RegN]->subtract(*caller_save_mask); - idealreg2debugmask[Op_RegI]->subtract(*caller_save_mask); - idealreg2debugmask[Op_RegL]->subtract(*caller_save_mask); - idealreg2debugmask[Op_RegF]->subtract(*caller_save_mask); - idealreg2debugmask[Op_RegD]->subtract(*caller_save_mask); - idealreg2debugmask[Op_RegP]->subtract(*caller_save_mask); - idealreg2debugmask[Op_RegVectMask]->subtract(*caller_save_mask); - - idealreg2debugmask[Op_VecA]->subtract(*caller_save_mask); - idealreg2debugmask[Op_VecS]->subtract(*caller_save_mask); - idealreg2debugmask[Op_VecD]->subtract(*caller_save_mask); - idealreg2debugmask[Op_VecX]->subtract(*caller_save_mask); - idealreg2debugmask[Op_VecY]->subtract(*caller_save_mask); - idealreg2debugmask[Op_VecZ]->subtract(*caller_save_mask); + idealreg2debugmask[Op_RegN]->SUBTRACT(*caller_save_mask); + idealreg2debugmask[Op_RegI]->SUBTRACT(*caller_save_mask); + idealreg2debugmask[Op_RegL]->SUBTRACT(*caller_save_mask); + idealreg2debugmask[Op_RegF]->SUBTRACT(*caller_save_mask); + idealreg2debugmask[Op_RegD]->SUBTRACT(*caller_save_mask); + idealreg2debugmask[Op_RegP]->SUBTRACT(*caller_save_mask); + idealreg2debugmask[Op_RegVectMask]->SUBTRACT(*caller_save_mask); + + idealreg2debugmask[Op_VecA]->SUBTRACT(*caller_save_mask); + idealreg2debugmask[Op_VecS]->SUBTRACT(*caller_save_mask); + idealreg2debugmask[Op_VecD]->SUBTRACT(*caller_save_mask); + idealreg2debugmask[Op_VecX]->SUBTRACT(*caller_save_mask); + idealreg2debugmask[Op_VecY]->SUBTRACT(*caller_save_mask); + idealreg2debugmask[Op_VecZ]->SUBTRACT(*caller_save_mask); } //---------------------------is_save_on_entry---------------------------------- @@ -702,9 +702,8 @@ void Matcher::Fixup_Save_On_Entry( ) { RegMask *ret_rms = init_input_masks( ret_edge_cnt + soe_cnt, _return_addr_mask, c_frame_ptr_mask ); // Returns have 0 or 1 returned values depending on call signature. // Return register is specified by return_value in the AD file. - if (ret_edge_cnt > TypeFunc::Parms) { - ret_rms[TypeFunc::Parms + 0].assignFrom(_return_value_mask); - } + if (ret_edge_cnt > TypeFunc::Parms) + ret_rms[TypeFunc::Parms+0] = _return_value_mask; // Input RegMask array shared by all ForwardExceptions uint forw_exc_edge_cnt = TypeFunc::Parms; @@ -716,10 +715,10 @@ void Matcher::Fixup_Save_On_Entry( ) { // Rethrow takes exception oop only, but in the argument 0 slot. OptoReg::Name reg = find_receiver(); if (reg >= 0) { - reth_rms[TypeFunc::Parms].assignFrom(mreg2regmask[reg]); + reth_rms[TypeFunc::Parms] = mreg2regmask[reg]; #ifdef _LP64 // Need two slots for ptrs in 64-bit land - reth_rms[TypeFunc::Parms].insert(OptoReg::add(OptoReg::Name(reg), 1)); + reth_rms[TypeFunc::Parms].Insert(OptoReg::add(OptoReg::Name(reg), 1)); #endif } @@ -738,8 +737,8 @@ void Matcher::Fixup_Save_On_Entry( ) { for( i=1; i < root->req(); i++ ) { MachReturnNode *m = root->in(i)->as_MachReturn(); if( m->ideal_Opcode() == Op_TailCall ) { - tail_call_rms[TypeFunc::Parms + 0].assignFrom(m->MachNode::in_RegMask(TypeFunc::Parms + 0)); - tail_call_rms[TypeFunc::Parms + 1].assignFrom(m->MachNode::in_RegMask(TypeFunc::Parms + 1)); + tail_call_rms[TypeFunc::Parms+0] = m->MachNode::in_RegMask(TypeFunc::Parms+0); + tail_call_rms[TypeFunc::Parms+1] = m->MachNode::in_RegMask(TypeFunc::Parms+1); break; } } @@ -751,8 +750,8 @@ void Matcher::Fixup_Save_On_Entry( ) { for( i=1; i < root->req(); i++ ) { MachReturnNode *m = root->in(i)->as_MachReturn(); if( m->ideal_Opcode() == Op_TailJump ) { - tail_jump_rms[TypeFunc::Parms + 0].assignFrom(m->MachNode::in_RegMask(TypeFunc::Parms + 0)); - tail_jump_rms[TypeFunc::Parms + 1].assignFrom(m->MachNode::in_RegMask(TypeFunc::Parms + 1)); + tail_jump_rms[TypeFunc::Parms+0] = m->MachNode::in_RegMask(TypeFunc::Parms+0); + tail_jump_rms[TypeFunc::Parms+1] = m->MachNode::in_RegMask(TypeFunc::Parms+1); break; } } @@ -785,14 +784,14 @@ void Matcher::Fixup_Save_On_Entry( ) { if( is_save_on_entry(i) ) { // Add the save-on-entry to the mask array - ret_rms [ ret_edge_cnt].assignFrom(mreg2regmask[i]); - reth_rms [ reth_edge_cnt].assignFrom(mreg2regmask[i]); - tail_call_rms[tail_call_edge_cnt].assignFrom(mreg2regmask[i]); - tail_jump_rms[tail_jump_edge_cnt].assignFrom(mreg2regmask[i]); - forw_exc_rms [ forw_exc_edge_cnt].assignFrom(mreg2regmask[i]); + ret_rms [ ret_edge_cnt] = mreg2regmask[i]; + reth_rms [ reth_edge_cnt] = mreg2regmask[i]; + tail_call_rms[tail_call_edge_cnt] = mreg2regmask[i]; + tail_jump_rms[tail_jump_edge_cnt] = mreg2regmask[i]; + forw_exc_rms [ forw_exc_edge_cnt] = mreg2regmask[i]; // Halts need the SOE registers, but only in the stack as debug info. // A just-prior uncommon-trap or deoptimization will use the SOE regs. - halt_rms [ halt_edge_cnt].assignFrom(*idealreg2spillmask[_register_save_type[i]]); + halt_rms [ halt_edge_cnt] = *idealreg2spillmask[_register_save_type[i]]; Node *mproj; @@ -803,12 +802,12 @@ void Matcher::Fixup_Save_On_Entry( ) { _register_save_type[i+1] == Op_RegF && is_save_on_entry(i+1) ) { // Add other bit for double - ret_rms [ ret_edge_cnt].insert(OptoReg::Name(i+1)); - reth_rms [ reth_edge_cnt].insert(OptoReg::Name(i+1)); - tail_call_rms[tail_call_edge_cnt].insert(OptoReg::Name(i+1)); - tail_jump_rms[tail_jump_edge_cnt].insert(OptoReg::Name(i+1)); - forw_exc_rms [ forw_exc_edge_cnt].insert(OptoReg::Name(i+1)); - halt_rms [ halt_edge_cnt].insert(OptoReg::Name(i+1)); + ret_rms [ ret_edge_cnt].Insert(OptoReg::Name(i+1)); + reth_rms [ reth_edge_cnt].Insert(OptoReg::Name(i+1)); + tail_call_rms[tail_call_edge_cnt].Insert(OptoReg::Name(i+1)); + tail_jump_rms[tail_jump_edge_cnt].Insert(OptoReg::Name(i+1)); + forw_exc_rms [ forw_exc_edge_cnt].Insert(OptoReg::Name(i+1)); + halt_rms [ halt_edge_cnt].Insert(OptoReg::Name(i+1)); mproj = new MachProjNode( start, proj_cnt, ret_rms[ret_edge_cnt], Op_RegD ); proj_cnt += 2; // Skip 2 for doubles } @@ -816,12 +815,12 @@ void Matcher::Fixup_Save_On_Entry( ) { _register_save_type[i-1] == Op_RegF && _register_save_type[i ] == Op_RegF && is_save_on_entry(i-1) ) { - ret_rms [ ret_edge_cnt].assignFrom(RegMask::EMPTY); - reth_rms [ reth_edge_cnt].assignFrom(RegMask::EMPTY); - tail_call_rms[tail_call_edge_cnt].assignFrom(RegMask::EMPTY); - tail_jump_rms[tail_jump_edge_cnt].assignFrom(RegMask::EMPTY); - forw_exc_rms [ forw_exc_edge_cnt].assignFrom(RegMask::EMPTY); - halt_rms [ halt_edge_cnt].assignFrom(RegMask::EMPTY); + ret_rms [ ret_edge_cnt] = RegMask::Empty; + reth_rms [ reth_edge_cnt] = RegMask::Empty; + tail_call_rms[tail_call_edge_cnt] = RegMask::Empty; + tail_jump_rms[tail_jump_edge_cnt] = RegMask::Empty; + forw_exc_rms [ forw_exc_edge_cnt] = RegMask::Empty; + halt_rms [ halt_edge_cnt] = RegMask::Empty; mproj = C->top(); } // Is this a RegI low half of a RegL? Double up 2 adjacent RegI's @@ -831,12 +830,12 @@ void Matcher::Fixup_Save_On_Entry( ) { _register_save_type[i+1] == Op_RegI && is_save_on_entry(i+1) ) { // Add other bit for long - ret_rms [ ret_edge_cnt].insert(OptoReg::Name(i+1)); - reth_rms [ reth_edge_cnt].insert(OptoReg::Name(i+1)); - tail_call_rms[tail_call_edge_cnt].insert(OptoReg::Name(i+1)); - tail_jump_rms[tail_jump_edge_cnt].insert(OptoReg::Name(i+1)); - forw_exc_rms [ forw_exc_edge_cnt].insert(OptoReg::Name(i+1)); - halt_rms [ halt_edge_cnt].insert(OptoReg::Name(i+1)); + ret_rms [ ret_edge_cnt].Insert(OptoReg::Name(i+1)); + reth_rms [ reth_edge_cnt].Insert(OptoReg::Name(i+1)); + tail_call_rms[tail_call_edge_cnt].Insert(OptoReg::Name(i+1)); + tail_jump_rms[tail_jump_edge_cnt].Insert(OptoReg::Name(i+1)); + forw_exc_rms [ forw_exc_edge_cnt].Insert(OptoReg::Name(i+1)); + halt_rms [ halt_edge_cnt].Insert(OptoReg::Name(i+1)); mproj = new MachProjNode( start, proj_cnt, ret_rms[ret_edge_cnt], Op_RegL ); proj_cnt += 2; // Skip 2 for longs } @@ -844,12 +843,12 @@ void Matcher::Fixup_Save_On_Entry( ) { _register_save_type[i-1] == Op_RegI && _register_save_type[i ] == Op_RegI && is_save_on_entry(i-1) ) { - ret_rms [ ret_edge_cnt].assignFrom(RegMask::EMPTY); - reth_rms [ reth_edge_cnt].assignFrom(RegMask::EMPTY); - tail_call_rms[tail_call_edge_cnt].assignFrom(RegMask::EMPTY); - tail_jump_rms[tail_jump_edge_cnt].assignFrom(RegMask::EMPTY); - forw_exc_rms [ forw_exc_edge_cnt].assignFrom(RegMask::EMPTY); - halt_rms [ halt_edge_cnt].assignFrom(RegMask::EMPTY); + ret_rms [ ret_edge_cnt] = RegMask::Empty; + reth_rms [ reth_edge_cnt] = RegMask::Empty; + tail_call_rms[tail_call_edge_cnt] = RegMask::Empty; + tail_jump_rms[tail_jump_edge_cnt] = RegMask::Empty; + forw_exc_rms [ forw_exc_edge_cnt] = RegMask::Empty; + halt_rms [ halt_edge_cnt] = RegMask::Empty; mproj = C->top(); } else { // Make a projection for it off the Start @@ -876,34 +875,34 @@ void Matcher::init_spill_mask( Node *ret ) { if( idealreg2regmask[Op_RegI] ) return; // One time only init OptoReg::c_frame_pointer = c_frame_pointer(); - c_frame_ptr_mask.assignFrom(RegMask(c_frame_pointer())); + c_frame_ptr_mask = RegMask(c_frame_pointer()); #ifdef _LP64 // pointers are twice as big - c_frame_ptr_mask.insert(OptoReg::add(c_frame_pointer(), 1)); + c_frame_ptr_mask.Insert(OptoReg::add(c_frame_pointer(),1)); #endif // Start at OptoReg::stack0() - STACK_ONLY_mask.clear(); + STACK_ONLY_mask.Clear(); // STACK_ONLY_mask is all stack bits - STACK_ONLY_mask.set_all_from(OptoReg::stack2reg(0)); + STACK_ONLY_mask.Set_All_From(OptoReg::stack2reg(0)); for (OptoReg::Name i = OptoReg::Name(0); i < OptoReg::Name(_last_Mach_Reg); i = OptoReg::add(i, 1)) { // Copy the register names over into the shared world. // SharedInfo::regName[i] = regName[i]; // Handy RegMasks per machine register - mreg2regmask[i].insert(i); + mreg2regmask[i].Insert(i); // Set up regmasks used to exclude save-on-call (and always-save) registers from debug masks. if (_register_save_policy[i] == 'C' || _register_save_policy[i] == 'A') { - caller_save_regmask.insert(i); + caller_save_regmask.Insert(i); } // Exclude save-on-entry registers from debug masks for stub compilations. if (_register_save_policy[i] == 'C' || _register_save_policy[i] == 'A' || _register_save_policy[i] == 'E') { - caller_save_regmask_exclude_soe.insert(i); + caller_save_regmask_exclude_soe.Insert(i); } } @@ -1241,8 +1240,8 @@ MachNode *Matcher::match_sfpt( SafePointNode *sfpt ) { } // Do all the pre-defined non-Empty register masks - msfpt->_in_rms[TypeFunc::ReturnAdr].assignFrom(_return_addr_mask); - msfpt->_in_rms[TypeFunc::FramePtr ].assignFrom(c_frame_ptr_mask); + msfpt->_in_rms[TypeFunc::ReturnAdr] = _return_addr_mask; + msfpt->_in_rms[TypeFunc::FramePtr ] = c_frame_ptr_mask; // Place first outgoing argument can possibly be put. OptoReg::Name begin_out_arg_area = OptoReg::add(_new_SP, C->out_preserve_stack_slots()); @@ -1316,17 +1315,17 @@ MachNode *Matcher::match_sfpt( SafePointNode *sfpt ) { OptoReg::Name reg_snd = OptoReg::as_OptoReg(second); assert (reg_fst <= reg_snd, "fst=%d snd=%d", reg_fst, reg_snd); for (OptoReg::Name r = reg_fst; r <= reg_snd; r++) { - rm->insert(r); + rm->Insert(r); } } // Grab first register, adjust stack slots and insert in mask. OptoReg::Name reg1 = warp_outgoing_stk_arg(first, begin_out_arg_area, out_arg_limit_per_call ); if (OptoReg::is_valid(reg1)) - rm->insert(reg1); + rm->Insert( reg1 ); // Grab second register (if any), adjust stack slots and insert in mask. OptoReg::Name reg2 = warp_outgoing_stk_arg(second, begin_out_arg_area, out_arg_limit_per_call ); if (OptoReg::is_valid(reg2)) - rm->insert(reg2); + rm->Insert( reg2 ); } // End of for all arguments } @@ -1343,11 +1342,11 @@ MachNode *Matcher::match_sfpt( SafePointNode *sfpt ) { // is excluded on the max-per-method basis, debug info cannot land in // this killed area. uint r_cnt = mcall->tf()->range()->cnt(); - MachProjNode* proj = new MachProjNode(mcall, r_cnt + 10000, RegMask::EMPTY, MachProjNode::fat_proj); + MachProjNode *proj = new MachProjNode( mcall, r_cnt+10000, RegMask::Empty, MachProjNode::fat_proj ); for (int i = begin_out_arg_area; i < out_arg_limit_per_call; i++) { - proj->_rout.insert(OptoReg::Name(i)); + proj->_rout.Insert(OptoReg::Name(i)); } - if (!proj->_rout.is_empty()) { + if (!proj->_rout.is_Empty()) { push_projection(proj); } } diff --git a/src/hotspot/share/opto/matcher.hpp b/src/hotspot/share/opto/matcher.hpp index e4396b423ac0e..0b609b70ab5e9 100644 --- a/src/hotspot/share/opto/matcher.hpp +++ b/src/hotspot/share/opto/matcher.hpp @@ -408,14 +408,14 @@ class Matcher : public PhaseTransform { static int inline_cache_reg_encode(); // Register for DIVI projection of divmodI - static const RegMask& divI_proj_mask(); + static RegMask divI_proj_mask(); // Register for MODI projection of divmodI - static const RegMask& modI_proj_mask(); + static RegMask modI_proj_mask(); // Register for DIVL projection of divmodL - static const RegMask& divL_proj_mask(); + static RegMask divL_proj_mask(); // Register for MODL projection of divmodL - static const RegMask& modL_proj_mask(); + static RegMask modL_proj_mask(); // Use hardware DIV instruction when it is faster than // a code which use multiply for division by constant. diff --git a/src/hotspot/share/opto/memnode.cpp b/src/hotspot/share/opto/memnode.cpp index 9187ef1a36150..2080b7cbeb521 100644 --- a/src/hotspot/share/opto/memnode.cpp +++ b/src/hotspot/share/opto/memnode.cpp @@ -4325,7 +4325,7 @@ Node *MemBarNode::match( const ProjNode *proj, const Matcher *m ) { switch (proj->_con) { case TypeFunc::Control: case TypeFunc::Memory: - return new MachProjNode(this, proj->_con, RegMask::EMPTY, MachProjNode::unmatched_proj); + return new MachProjNode(this,proj->_con,RegMask::Empty,MachProjNode::unmatched_proj); } ShouldNotReachHere(); return nullptr; @@ -4572,7 +4572,7 @@ const RegMask &InitializeNode::in_RegMask(uint idx) const { // This edge should be set to top, by the set_complete. But be conservative. if (idx == InitializeNode::RawAddress) return *(Compile::current()->matcher()->idealreg2spillmask[in(idx)->ideal_reg()]); - return RegMask::EMPTY; + return RegMask::Empty; } Node* InitializeNode::memory(uint alias_idx) { @@ -5784,7 +5784,7 @@ void MergeMemNode::set_base_memory(Node *new_base) { //------------------------------out_RegMask------------------------------------ const RegMask &MergeMemNode::out_RegMask() const { - return RegMask::EMPTY; + return RegMask::Empty; } //------------------------------dump_spec-------------------------------------- diff --git a/src/hotspot/share/opto/mempointer.cpp b/src/hotspot/share/opto/mempointer.cpp index 68abaffe6429a..a63ba8ef7010b 100644 --- a/src/hotspot/share/opto/mempointer.cpp +++ b/src/hotspot/share/opto/mempointer.cpp @@ -112,7 +112,7 @@ void MemPointerParser::canonicalize_raw_summands() { } } // Keep summands with non-zero scale. - if (!scaleI.is_zero() && !scaleL.is_zero()) { + if (!scaleI.is_zero() && !scaleL.is_NaN()) { _raw_summands.at_put(pos_put++, MemPointerRawSummand(variable, scaleI, scaleL, int_group)); } } diff --git a/src/hotspot/share/opto/mulnode.cpp b/src/hotspot/share/opto/mulnode.cpp index 1e757c2be8110..4691c6a45b063 100644 --- a/src/hotspot/share/opto/mulnode.cpp +++ b/src/hotspot/share/opto/mulnode.cpp @@ -963,7 +963,7 @@ static bool const_shift_count(PhaseGVN* phase, const Node* shift_node, int* coun } // Returns whether the shift amount is constant. If so, sets real_shift and masked_shift. -static bool mask_shift_amount(PhaseGVN* phase, const Node* shift_node, uint nBits, int& real_shift, uint& masked_shift) { +static bool mask_shift_amount(PhaseGVN* phase, const Node* shift_node, uint nBits, int& real_shift, int& masked_shift) { if (const_shift_count(phase, shift_node, &real_shift)) { masked_shift = real_shift & (nBits - 1); return true; @@ -972,23 +972,23 @@ static bool mask_shift_amount(PhaseGVN* phase, const Node* shift_node, uint nBit } // Convenience for when we don't care about the real amount -static bool mask_shift_amount(PhaseGVN* phase, const Node* shift_node, uint nBits, uint& masked_shift) { +static bool mask_shift_amount(PhaseGVN* phase, const Node* shift_node, uint nBits, int& masked_shift) { int real_shift; return mask_shift_amount(phase, shift_node, nBits, real_shift, masked_shift); } // Use this in ::Ideal only with shiftNode == this! // Returns the masked shift amount if constant or 0 if not constant. -static uint mask_and_replace_shift_amount(PhaseGVN* phase, Node* shift_node, uint nBits) { +static int mask_and_replace_shift_amount(PhaseGVN* phase, Node* shift_node, uint nBits) { int real_shift; - uint masked_shift; + int masked_shift; if (mask_shift_amount(phase, shift_node, nBits, real_shift, masked_shift)) { if (masked_shift == 0) { // Let Identity() handle 0 shift count. return 0; } - if (real_shift != (int)masked_shift) { + if (real_shift != masked_shift) { PhaseIterGVN* igvn = phase->is_IterGVN(); if (igvn != nullptr) { igvn->_worklist.push(shift_node); @@ -1013,15 +1013,15 @@ static uint mask_and_replace_shift_amount(PhaseGVN* phase, Node* shift_node, uin // There are 2 cases: // if con_outer + con_inner >= nbits => 0 // if con_outer + con_inner < nbits => X << (con_outer + con_inner) -static Node* collapse_nested_shift_left(PhaseGVN* phase, const Node* outer_shift, uint con_outer, BasicType bt) { +static Node* collapse_nested_shift_left(PhaseGVN* phase, const Node* outer_shift, int con_outer, BasicType bt) { assert(bt == T_LONG || bt == T_INT, "Unexpected type"); const Node* inner_shift = outer_shift->in(1); if (inner_shift->Opcode() != Op_LShift(bt)) { return nullptr; } - uint nbits = bits_per_java_integer(bt); - uint con_inner; + int nbits = static_cast(bits_per_java_integer(bt)); + int con_inner; if (!mask_shift_amount(phase, inner_shift, nbits, con_inner)) { return nullptr; } @@ -1046,81 +1046,86 @@ static Node* collapse_nested_shift_left(PhaseGVN* phase, const Node* outer_shift //------------------------------Identity--------------------------------------- Node* LShiftINode::Identity(PhaseGVN* phase) { - return IdentityIL(phase, T_INT); + int count = 0; + if (const_shift_count(phase, this, &count) && (count & (BitsPerJavaInteger - 1)) == 0) { + // Shift by a multiple of 32 does nothing + return in(1); + } + return this; } -Node* LShiftNode::IdealIL(PhaseGVN* phase, bool can_reshape, BasicType bt) { - uint con = mask_and_replace_shift_amount(phase, this, bits_per_java_integer(bt)); +//------------------------------Ideal------------------------------------------ +// If the right input is a constant, and the left input is an add of a +// constant, flatten the tree: (X+con1)< X< X << (con1 + con2) +Node *LShiftINode::Ideal(PhaseGVN *phase, bool can_reshape) { + int con = mask_and_replace_shift_amount(phase, this, BitsPerJavaInteger); if (con == 0) { return nullptr; } - // If the right input is a constant, and the left input is an add of a - // constant, flatten the tree: (X+con1)< X<Opcode(); - if (add1_op == Op_Add(bt)) { // Left input is an add? - assert(add1 != add1->in(1), "dead loop in LShiftINode::Ideal"); + if( add1_op == Op_AddI ) { // Left input is an add? + assert( add1 != add1->in(1), "dead loop in LShiftINode::Ideal" ); // Transform is legal, but check for profit. Avoid breaking 'i2s' // and 'i2b' patterns which typically fold into 'StoreC/StoreB'. - if (bt != T_INT || con < 16) { + if( con < 16 ) { // Left input is an add of the same number? - if (con != (bits_per_java_integer(bt) - 1) && add1->in(1) == add1->in(2)) { + if (add1->in(1) == add1->in(2)) { // Convert "(x + x) << c0" into "x << (c0 + 1)" - // In general, this optimization cannot be applied for c0 == 31 (for LShiftI) since + // In general, this optimization cannot be applied for c0 == 31 since // 2x << 31 != x << 32 = x << 0 = x (e.g. x = 1: 2 << 31 = 0 != 1) - // or c0 != 63 (for LShiftL) because: - // (x + x) << 63 = 2x << 63, while - // (x + x) << 63 --transform--> x << 64 = x << 0 = x (!= 2x << 63, for example for x = 1) - // According to the Java spec, chapter 15.19, we only consider the six lowest-order bits of the right-hand operand - // (i.e. "right-hand operand" & 0b111111). Therefore, x << 64 is the same as x << 0 (64 = 0b10000000 & 0b0111111 = 0). - return LShiftNode::make(add1->in(1), phase->intcon(con + 1), bt); + return new LShiftINode(add1->in(1), phase->intcon(con + 1)); } // Left input is an add of a constant? - const TypeInteger* t12 = phase->type(add1->in(2))->isa_integer(bt); - if (t12 != nullptr && t12->is_con()) { // Left input is an add of a con? + const TypeInt *t12 = phase->type(add1->in(2))->isa_int(); + if( t12 && t12->is_con() ){ // Left input is an add of a con? // Compute X << con0 - Node* lsh = phase->transform(LShiftNode::make(add1->in(1), in(2), bt)); + Node *lsh = phase->transform( new LShiftINode( add1->in(1), in(2) ) ); // Compute X<integercon(java_shift_left(t12->get_con_as_long(bt), con, bt), bt), bt); + return new AddINode( lsh, phase->intcon(t12->get_con() << con)); } } } // Check for "(x >> C1) << C2" - if (add1_op == Op_RShift(bt) || add1_op == Op_URShift(bt)) { + if (add1_op == Op_RShiftI || add1_op == Op_URShiftI) { int add1Con = 0; const_shift_count(phase, add1, &add1Con); // Special case C1 == C2, which just masks off low bits - if (add1Con > 0 && con == (uint)add1Con) { + if (add1Con > 0 && con == add1Con) { // Convert to "(x & -(1 << C2))" - return MulNode::make_and(add1->in(1), phase->integercon(java_negate(java_shift_left(1, con, bt), bt), bt), bt); + return new AndINode(add1->in(1), phase->intcon(java_negate(jint(1 << con)))); } else { // Wait until the right shift has been sharpened to the correct count - if (add1Con > 0 && (uint)add1Con < bits_per_java_integer(bt)) { + if (add1Con > 0 && add1Con < BitsPerJavaInteger) { // As loop parsing can produce LShiftI nodes, we should wait until the graph is fully formed // to apply optimizations, otherwise we can inadvertently stop vectorization opportunities. if (phase->is_IterGVN()) { - if (con > (uint)add1Con) { + if (con > add1Con) { // Creates "(x << (C2 - C1)) & -(1 << C2)" - Node* lshift = phase->transform(LShiftNode::make(add1->in(1), phase->intcon(con - add1Con), bt)); - return MulNode::make_and(lshift, phase->integercon(java_negate(java_shift_left(1, con, bt), bt), bt), bt); + Node* lshift = phase->transform(new LShiftINode(add1->in(1), phase->intcon(con - add1Con))); + return new AndINode(lshift, phase->intcon(java_negate(jint(1 << con)))); } else { - assert(con < (uint)add1Con, "must be (%d < %d)", con, add1Con); + assert(con < add1Con, "must be (%d < %d)", con, add1Con); // Creates "(x >> (C1 - C2)) & -(1 << C2)" // Handle logical and arithmetic shifts Node* rshift; - if (add1_op == Op_RShift(bt)) { - rshift = phase->transform(RShiftNode::make(add1->in(1), phase->intcon(add1Con - con), bt)); + if (add1_op == Op_RShiftI) { + rshift = phase->transform(new RShiftINode(add1->in(1), phase->intcon(add1Con - con))); } else { - rshift = phase->transform(URShiftNode::make(add1->in(1), phase->intcon(add1Con - con), bt)); + rshift = phase->transform(new URShiftINode(add1->in(1), phase->intcon(add1Con - con))); } - return MulNode::make_and(rshift, phase->integercon(java_negate(java_shift_left(1, con, bt)), bt), bt); + return new AndINode(rshift, phase->intcon(java_negate(jint(1 << con)))); } } else { phase->record_for_igvn(this); @@ -1130,29 +1135,29 @@ Node* LShiftNode::IdealIL(PhaseGVN* phase, bool can_reshape, BasicType bt) { } // Check for "((x >> C1) & Y) << C2" - if (add1_op == Op_And(bt)) { - Node* add2 = add1->in(1); + if (add1_op == Op_AndI) { + Node *add2 = add1->in(1); int add2_op = add2->Opcode(); - if (add2_op == Op_RShift(bt) || add2_op == Op_URShift(bt)) { + if (add2_op == Op_RShiftI || add2_op == Op_URShiftI) { // Special case C1 == C2, which just masks off low bits if (add2->in(2) == in(2)) { // Convert to "(x & (Y << C2))" - Node* y_sh = phase->transform(LShiftNode::make(add1->in(2), phase->intcon(con), bt)); - return MulNode::make_and(add2->in(1), y_sh, bt); + Node* y_sh = phase->transform(new LShiftINode(add1->in(2), phase->intcon(con))); + return new AndINode(add2->in(1), y_sh); } int add2Con = 0; const_shift_count(phase, add2, &add2Con); - if (add2Con > 0 && (uint)add2Con < bits_per_java_integer(bt)) { + if (add2Con > 0 && add2Con < BitsPerJavaInteger) { if (phase->is_IterGVN()) { // Convert to "((x >> C1) << C2) & (Y << C2)" // Make "(x >> C1) << C2", which will get folded away by the rule above - Node* x_sh = phase->transform(LShiftNode::make(add2, phase->intcon(con), bt)); + Node* x_sh = phase->transform(new LShiftINode(add2, phase->intcon(con))); // Make "Y << C2", which will simplify when Y is a constant - Node* y_sh = phase->transform(LShiftNode::make(add1->in(2), phase->intcon(con), bt)); + Node* y_sh = phase->transform(new LShiftINode(add1->in(2), phase->intcon(con))); - return MulNode::make_and(x_sh, y_sh, bt); + return new AndINode(x_sh, y_sh); } else { phase->record_for_igvn(this); } @@ -1162,16 +1167,14 @@ Node* LShiftNode::IdealIL(PhaseGVN* phase, bool can_reshape, BasicType bt) { // Check for ((x & ((1<<(32-c0))-1)) << c0) which ANDs off high bits // before shifting them away. - const jlong bits_mask = max_unsigned_integer(bt) >> con; - assert(bt != T_INT || bits_mask == right_n_bits(bits_per_java_integer(bt)-con), "inconsistent"); - if (add1_op == Op_And(bt) && - phase->type(add1->in(2)) == TypeInteger::make(bits_mask, bt)) { - return LShiftNode::make(add1->in(1), in(2), bt); - } + const jint bits_mask = right_n_bits(BitsPerJavaInteger-con); + if( add1_op == Op_AndI && + phase->type(add1->in(2)) == TypeInt::make( bits_mask ) ) + return new LShiftINode( add1->in(1), in(2) ); - // Collapse nested left-shifts with constant rhs: + // Performs: // (X << con1) << con2 ==> X << (con1 + con2) - Node* doubleShift = collapse_nested_shift_left(phase, this, con, bt); + Node* doubleShift = collapse_nested_shift_left(phase, this, con, T_INT); if (doubleShift != nullptr) { return doubleShift; } @@ -1179,103 +1182,237 @@ Node* LShiftNode::IdealIL(PhaseGVN* phase, bool can_reshape, BasicType bt) { return nullptr; } -//------------------------------Ideal------------------------------------------ -Node* LShiftINode::Ideal(PhaseGVN *phase, bool can_reshape) { - return IdealIL(phase, can_reshape, T_INT); -} - -const Type* LShiftNode::ValueIL(PhaseGVN* phase, BasicType bt) const { - const Type* t1 = phase->type(in(1)); - const Type* t2 = phase->type(in(2)); +//------------------------------Value------------------------------------------ +// A LShiftINode shifts its input2 left by input1 amount. +const Type* LShiftINode::Value(PhaseGVN* phase) const { + const Type *t1 = phase->type( in(1) ); + const Type *t2 = phase->type( in(2) ); // Either input is TOP ==> the result is TOP - if (t1 == Type::TOP) { - return Type::TOP; - } - if (t2 == Type::TOP) { - return Type::TOP; - } + if( t1 == Type::TOP ) return Type::TOP; + if( t2 == Type::TOP ) return Type::TOP; // Left input is ZERO ==> the result is ZERO. - if (t1 == TypeInteger::zero(bt)) { - return TypeInteger::zero(bt); - } + if( t1 == TypeInt::ZERO ) return TypeInt::ZERO; // Shift by zero does nothing - if (t2 == TypeInt::ZERO) { - return t1; - } + if( t2 == TypeInt::ZERO ) return t1; // Either input is BOTTOM ==> the result is BOTTOM - if ((t1 == TypeInteger::bottom(bt)) || (t2 == TypeInt::INT) || - (t1 == Type::BOTTOM) || (t2 == Type::BOTTOM)) { - return TypeInteger::bottom(bt); - } + if( (t1 == TypeInt::INT) || (t2 == TypeInt::INT) || + (t1 == Type::BOTTOM) || (t2 == Type::BOTTOM) ) + return TypeInt::INT; - const TypeInteger* r1 = t1->is_integer(bt); // Handy access - const TypeInt* r2 = t2->is_int(); // Handy access + const TypeInt *r1 = t1->is_int(); // Handy access + const TypeInt *r2 = t2->is_int(); // Handy access - if (!r2->is_con()) { - return TypeInteger::bottom(bt); - } + if (!r2->is_con()) + return TypeInt::INT; uint shift = r2->get_con(); - shift &= bits_per_java_integer(bt) - 1; // semantics of Java shifts - // Shift by a multiple of 32/64 does nothing: - if (shift == 0) { - return t1; - } + shift &= BitsPerJavaInteger-1; // semantics of Java shifts + // Shift by a multiple of 32 does nothing: + if (shift == 0) return t1; // If the shift is a constant, shift the bounds of the type, // unless this could lead to an overflow. if (!r1->is_con()) { - jlong lo = r1->lo_as_long(), hi = r1->hi_as_long(); -#ifdef ASSERT - if (bt == T_INT) { - jint lo_int = r1->is_int()->_lo, hi_int = r1->is_int()->_hi; - assert((java_shift_right(java_shift_left(lo, shift, bt), shift, bt) == lo) == (((lo_int << shift) >> shift) == lo_int), "inconsistent"); - assert((java_shift_right(java_shift_left(hi, shift, bt), shift, bt) == hi) == (((hi_int << shift) >> shift) == hi_int), "inconsistent"); - } -#endif - if (java_shift_right(java_shift_left(lo, shift, bt), shift, bt) == lo && - java_shift_right(java_shift_left(hi, shift, bt), shift, bt) == hi) { + jint lo = r1->_lo, hi = r1->_hi; + if (((lo << shift) >> shift) == lo && + ((hi << shift) >> shift) == hi) { // No overflow. The range shifts up cleanly. - return TypeInteger::make(java_shift_left(lo, shift, bt), - java_shift_left(hi, shift, bt), - MAX2(r1->_widen, r2->_widen), bt); + return TypeInt::make((jint)lo << (jint)shift, + (jint)hi << (jint)shift, + MAX2(r1->_widen,r2->_widen)); } - return TypeInteger::bottom(bt); + return TypeInt::INT; } - return TypeInteger::make(java_shift_left(r1->get_con_as_long(bt), shift, bt), bt); -} - -//------------------------------Value------------------------------------------ -const Type* LShiftINode::Value(PhaseGVN* phase) const { - return ValueIL(phase, T_INT); + return TypeInt::make( (jint)r1->get_con() << (jint)shift ); } -Node* LShiftNode::IdentityIL(PhaseGVN* phase, BasicType bt) { +//============================================================================= +//------------------------------Identity--------------------------------------- +Node* LShiftLNode::Identity(PhaseGVN* phase) { int count = 0; - if (const_shift_count(phase, this, &count) && (count & (bits_per_java_integer(bt) - 1)) == 0) { - // Shift by a multiple of 32/64 does nothing + if (const_shift_count(phase, this, &count) && (count & (BitsPerJavaLong - 1)) == 0) { + // Shift by a multiple of 64 does nothing return in(1); } return this; } -//============================================================================= -//------------------------------Identity--------------------------------------- -Node* LShiftLNode::Identity(PhaseGVN* phase) { - return IdentityIL(phase, T_LONG); -} - //------------------------------Ideal------------------------------------------ -Node* LShiftLNode::Ideal(PhaseGVN* phase, bool can_reshape) { - return IdealIL(phase, can_reshape, T_LONG); +// If the right input is a constant, and the left input is an add of a +// constant, flatten the tree: (X+con1)< X< X << (con1 + con2) +Node *LShiftLNode::Ideal(PhaseGVN *phase, bool can_reshape) { + int con = mask_and_replace_shift_amount(phase, this, BitsPerJavaLong); + if (con == 0) { + return nullptr; + } + + // Left input is an add? + Node *add1 = in(1); + int add1_op = add1->Opcode(); + if( add1_op == Op_AddL ) { // Left input is an add? + // Avoid dead data cycles from dead loops + assert( add1 != add1->in(1), "dead loop in LShiftLNode::Ideal" ); + + // Left input is an add of the same number? + if (con != (BitsPerJavaLong - 1) && add1->in(1) == add1->in(2)) { + // Convert "(x + x) << c0" into "x << (c0 + 1)" + // Can only be applied if c0 != 63 because: + // (x + x) << 63 = 2x << 63, while + // (x + x) << 63 --transform--> x << 64 = x << 0 = x (!= 2x << 63, for example for x = 1) + // According to the Java spec, chapter 15.19, we only consider the six lowest-order bits of the right-hand operand + // (i.e. "right-hand operand" & 0b111111). Therefore, x << 64 is the same as x << 0 (64 = 0b10000000 & 0b0111111 = 0). + return new LShiftLNode(add1->in(1), phase->intcon(con + 1)); + } + + // Left input is an add of a constant? + const TypeLong *t12 = phase->type(add1->in(2))->isa_long(); + if( t12 && t12->is_con() ){ // Left input is an add of a con? + // Compute X << con0 + Node *lsh = phase->transform( new LShiftLNode( add1->in(1), in(2) ) ); + // Compute X<longcon(t12->get_con() << con)); + } + } + + // Check for "(x >> C1) << C2" + if (add1_op == Op_RShiftL || add1_op == Op_URShiftL) { + int add1Con = 0; + const_shift_count(phase, add1, &add1Con); + + // Special case C1 == C2, which just masks off low bits + if (add1Con > 0 && con == add1Con) { + // Convert to "(x & -(1 << C2))" + return new AndLNode(add1->in(1), phase->longcon(java_negate(jlong(CONST64(1) << con)))); + } else { + // Wait until the right shift has been sharpened to the correct count + if (add1Con > 0 && add1Con < BitsPerJavaLong) { + // As loop parsing can produce LShiftI nodes, we should wait until the graph is fully formed + // to apply optimizations, otherwise we can inadvertently stop vectorization opportunities. + if (phase->is_IterGVN()) { + if (con > add1Con) { + // Creates "(x << (C2 - C1)) & -(1 << C2)" + Node* lshift = phase->transform(new LShiftLNode(add1->in(1), phase->intcon(con - add1Con))); + return new AndLNode(lshift, phase->longcon(java_negate(jlong(CONST64(1) << con)))); + } else { + assert(con < add1Con, "must be (%d < %d)", con, add1Con); + // Creates "(x >> (C1 - C2)) & -(1 << C2)" + + // Handle logical and arithmetic shifts + Node* rshift; + if (add1_op == Op_RShiftL) { + rshift = phase->transform(new RShiftLNode(add1->in(1), phase->intcon(add1Con - con))); + } else { + rshift = phase->transform(new URShiftLNode(add1->in(1), phase->intcon(add1Con - con))); + } + + return new AndLNode(rshift, phase->longcon(java_negate(jlong(CONST64(1) << con)))); + } + } else { + phase->record_for_igvn(this); + } + } + } + } + + // Check for "((x >> C1) & Y) << C2" + if (add1_op == Op_AndL) { + Node* add2 = add1->in(1); + int add2_op = add2->Opcode(); + if (add2_op == Op_RShiftL || add2_op == Op_URShiftL) { + // Special case C1 == C2, which just masks off low bits + if (add2->in(2) == in(2)) { + // Convert to "(x & (Y << C2))" + Node* y_sh = phase->transform(new LShiftLNode(add1->in(2), phase->intcon(con))); + return new AndLNode(add2->in(1), y_sh); + } + + int add2Con = 0; + const_shift_count(phase, add2, &add2Con); + if (add2Con > 0 && add2Con < BitsPerJavaLong) { + if (phase->is_IterGVN()) { + // Convert to "((x >> C1) << C2) & (Y << C2)" + + // Make "(x >> C1) << C2", which will get folded away by the rule above + Node* x_sh = phase->transform(new LShiftLNode(add2, phase->intcon(con))); + // Make "Y << C2", which will simplify when Y is a constant + Node* y_sh = phase->transform(new LShiftLNode(add1->in(2), phase->intcon(con))); + + return new AndLNode(x_sh, y_sh); + } else { + phase->record_for_igvn(this); + } + } + } + } + + // Check for ((x & ((CONST64(1)<<(64-c0))-1)) << c0) which ANDs off high bits + // before shifting them away. + const jlong bits_mask = jlong(max_julong >> con); + if( add1_op == Op_AndL && + phase->type(add1->in(2)) == TypeLong::make( bits_mask ) ) + return new LShiftLNode( add1->in(1), in(2) ); + + // Performs: + // (X << con1) << con2 ==> X << (con1 + con2) + Node* doubleShift = collapse_nested_shift_left(phase, this, con, T_LONG); + if (doubleShift != nullptr) { + return doubleShift; + } + + return nullptr; } //------------------------------Value------------------------------------------ +// A LShiftLNode shifts its input2 left by input1 amount. const Type* LShiftLNode::Value(PhaseGVN* phase) const { - return ValueIL(phase, T_LONG); + const Type *t1 = phase->type( in(1) ); + const Type *t2 = phase->type( in(2) ); + // Either input is TOP ==> the result is TOP + if( t1 == Type::TOP ) return Type::TOP; + if( t2 == Type::TOP ) return Type::TOP; + + // Left input is ZERO ==> the result is ZERO. + if( t1 == TypeLong::ZERO ) return TypeLong::ZERO; + // Shift by zero does nothing + if( t2 == TypeInt::ZERO ) return t1; + + // Either input is BOTTOM ==> the result is BOTTOM + if( (t1 == TypeLong::LONG) || (t2 == TypeInt::INT) || + (t1 == Type::BOTTOM) || (t2 == Type::BOTTOM) ) + return TypeLong::LONG; + + const TypeLong *r1 = t1->is_long(); // Handy access + const TypeInt *r2 = t2->is_int(); // Handy access + + if (!r2->is_con()) + return TypeLong::LONG; + + uint shift = r2->get_con(); + shift &= BitsPerJavaLong - 1; // semantics of Java shifts + // Shift by a multiple of 64 does nothing: + if (shift == 0) return t1; + + // If the shift is a constant, shift the bounds of the type, + // unless this could lead to an overflow. + if (!r1->is_con()) { + jlong lo = r1->_lo, hi = r1->_hi; + if (((lo << shift) >> shift) == lo && + ((hi << shift) >> shift) == hi) { + // No overflow. The range shifts up cleanly. + return TypeLong::make((jlong)lo << (jint)shift, + (jlong)hi << (jint)shift, + MAX2(r1->_widen,r2->_widen)); + } + return TypeLong::LONG; + } + + return TypeLong::make( (jlong)r1->get_con() << (jint)shift ); } RShiftNode* RShiftNode::make(Node* in1, Node* in2, BasicType bt) { @@ -1512,18 +1649,6 @@ const Type* RShiftLNode::Value(PhaseGVN* phase) const { return ValueIL(phase, T_LONG); } -URShiftNode* URShiftNode::make(Node* in1, Node* in2, BasicType bt) { - switch (bt) { - case T_INT: - return new URShiftINode(in1, in2); - case T_LONG: - return new URShiftLNode(in1, in2); - default: - fatal("Not implemented for %s", type2name(bt)); - } - return nullptr; -} - //============================================================================= //------------------------------Identity--------------------------------------- Node* URShiftINode::Identity(PhaseGVN* phase) { @@ -1559,7 +1684,7 @@ Node* URShiftINode::Identity(PhaseGVN* phase) { } //------------------------------Ideal------------------------------------------ -Node* URShiftINode::Ideal(PhaseGVN* phase, bool can_reshape) { +Node *URShiftINode::Ideal(PhaseGVN *phase, bool can_reshape) { int con = mask_and_replace_shift_amount(phase, this, BitsPerJavaInteger); if (con == 0) { return nullptr; @@ -1723,7 +1848,7 @@ Node* URShiftLNode::Identity(PhaseGVN* phase) { } //------------------------------Ideal------------------------------------------ -Node* URShiftLNode::Ideal(PhaseGVN* phase, bool can_reshape) { +Node *URShiftLNode::Ideal(PhaseGVN *phase, bool can_reshape) { int con = mask_and_replace_shift_amount(phase, this, BitsPerJavaLong); if (con == 0) { return nullptr; diff --git a/src/hotspot/share/opto/mulnode.hpp b/src/hotspot/share/opto/mulnode.hpp index 1e19e8ec5cd70..b736c17b30034 100644 --- a/src/hotspot/share/opto/mulnode.hpp +++ b/src/hotspot/share/opto/mulnode.hpp @@ -260,14 +260,10 @@ inline Node* make_and(Node* a, Node* b) { class LShiftNode : public Node { public: - LShiftNode(Node* in1, Node* in2) : Node(nullptr,in1,in2) { + LShiftNode(Node *in1, Node *in2) : Node(nullptr,in1,in2) { init_class_id(Class_LShift); } - const Type* ValueIL(PhaseGVN* phase, BasicType bt) const; - Node* IdentityIL(PhaseGVN* phase, BasicType bt); - Node* IdealIL(PhaseGVN* phase, bool can_reshape, BasicType bt); - static LShiftNode* make(Node* in1, Node* in2, BasicType bt); }; @@ -275,12 +271,12 @@ class LShiftNode : public Node { // Logical shift left class LShiftINode : public LShiftNode { public: - LShiftINode(Node* in1, Node* in2) : LShiftNode(in1,in2) {} + LShiftINode(Node *in1, Node *in2) : LShiftNode(in1,in2) {} virtual int Opcode() const; virtual Node* Identity(PhaseGVN* phase); - virtual Node* Ideal(PhaseGVN *phase, bool can_reshape); + virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); virtual const Type* Value(PhaseGVN* phase) const; - const Type* bottom_type() const { return TypeInt::INT; } + const Type *bottom_type() const { return TypeInt::INT; } virtual uint ideal_reg() const { return Op_RegI; } }; @@ -291,9 +287,9 @@ class LShiftLNode : public LShiftNode { LShiftLNode(Node *in1, Node *in2) : LShiftNode(in1,in2) {} virtual int Opcode() const; virtual Node* Identity(PhaseGVN* phase); - virtual Node* Ideal(PhaseGVN *phase, bool can_reshape); + virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); virtual const Type* Value(PhaseGVN* phase) const; - const Type* bottom_type() const { return TypeLong::LONG; } + const Type *bottom_type() const { return TypeLong::LONG; } virtual uint ideal_reg() const { return Op_RegL; } }; @@ -362,17 +358,11 @@ class RShiftLNode : public RShiftNode { virtual uint ideal_reg() const { return Op_RegL; } }; -class URShiftNode : public Node { -public: - URShiftNode(Node* in1, Node* in2) : Node(nullptr, in1, in2) {} - static URShiftNode* make(Node* in1, Node* in2, BasicType bt); -}; - //------------------------------URShiftBNode----------------------------------- // Logical shift right -class URShiftBNode : public URShiftNode { +class URShiftBNode : public Node { public: - URShiftBNode(Node* in1, Node* in2) : URShiftNode(in1,in2) { + URShiftBNode( Node *in1, Node *in2 ) : Node(nullptr,in1,in2) { ShouldNotReachHere(); // only vector variant is used } virtual int Opcode() const; @@ -380,9 +370,9 @@ class URShiftBNode : public URShiftNode { //------------------------------URShiftSNode----------------------------------- // Logical shift right -class URShiftSNode : public URShiftNode { +class URShiftSNode : public Node { public: - URShiftSNode(Node* in1, Node* in2) : URShiftNode(in1,in2) { + URShiftSNode( Node *in1, Node *in2 ) : Node(nullptr,in1,in2) { ShouldNotReachHere(); // only vector variant is used } virtual int Opcode() const; @@ -390,27 +380,27 @@ class URShiftSNode : public URShiftNode { //------------------------------URShiftINode----------------------------------- // Logical shift right -class URShiftINode : public URShiftNode { +class URShiftINode : public Node { public: - URShiftINode(Node* in1, Node* in2) : URShiftNode(in1,in2) {} + URShiftINode( Node *in1, Node *in2 ) : Node(nullptr,in1,in2) {} virtual int Opcode() const; virtual Node* Identity(PhaseGVN* phase); - virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); + virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); virtual const Type* Value(PhaseGVN* phase) const; - const Type* bottom_type() const { return TypeInt::INT; } + const Type *bottom_type() const { return TypeInt::INT; } virtual uint ideal_reg() const { return Op_RegI; } }; //------------------------------URShiftLNode----------------------------------- // Logical shift right -class URShiftLNode : public URShiftNode { +class URShiftLNode : public Node { public: - URShiftLNode(Node* in1, Node* in2) : URShiftNode(in1,in2) {} + URShiftLNode( Node *in1, Node *in2 ) : Node(nullptr,in1,in2) {} virtual int Opcode() const; virtual Node* Identity(PhaseGVN* phase); - virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); + virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); virtual const Type* Value(PhaseGVN* phase) const; - const Type* bottom_type() const { return TypeLong::LONG; } + const Type *bottom_type() const { return TypeLong::LONG; } virtual uint ideal_reg() const { return Op_RegL; } }; diff --git a/src/hotspot/share/opto/multnode.cpp b/src/hotspot/share/opto/multnode.cpp index 4d8d1f4246c2a..f429d5daac076 100644 --- a/src/hotspot/share/opto/multnode.cpp +++ b/src/hotspot/share/opto/multnode.cpp @@ -36,7 +36,7 @@ //============================================================================= //------------------------------MultiNode-------------------------------------- const RegMask &MultiNode::out_RegMask() const { - return RegMask::EMPTY; + return RegMask::Empty; } Node *MultiNode::match( const ProjNode *proj, const Matcher *m ) { return proj->clone(); } @@ -185,7 +185,7 @@ const Type* ProjNode::Value(PhaseGVN* phase) const { //------------------------------out_RegMask------------------------------------ // Pass the buck uphill const RegMask &ProjNode::out_RegMask() const { - return RegMask::EMPTY; + return RegMask::Empty; } //------------------------------ideal_reg-------------------------------------- diff --git a/src/hotspot/share/opto/node.cpp b/src/hotspot/share/opto/node.cpp index 497d0d1aeb0bd..cca98bd8abaf2 100644 --- a/src/hotspot/share/opto/node.cpp +++ b/src/hotspot/share/opto/node.cpp @@ -2800,12 +2800,12 @@ uint Node::match_edge(uint idx) const { // Register classes are defined for specific machines const RegMask &Node::out_RegMask() const { ShouldNotCallThis(); - return RegMask::EMPTY; + return RegMask::Empty; } const RegMask &Node::in_RegMask(uint) const { ShouldNotCallThis(); - return RegMask::EMPTY; + return RegMask::Empty; } void Node_Array::grow(uint i) { diff --git a/src/hotspot/share/opto/node.hpp b/src/hotspot/share/opto/node.hpp index 9ce9e705eec27..c2b3c4fb0ad25 100644 --- a/src/hotspot/share/opto/node.hpp +++ b/src/hotspot/share/opto/node.hpp @@ -2086,7 +2086,6 @@ Op_IL(Sub) Op_IL(Mul) Op_IL(URShift) Op_IL(LShift) -Op_IL(RShift) Op_IL(Xor) Op_IL(Cmp) Op_IL(Div) diff --git a/src/hotspot/share/opto/postaloc.cpp b/src/hotspot/share/opto/postaloc.cpp index c961340e71acf..56d3ba6bbe002 100644 --- a/src/hotspot/share/opto/postaloc.cpp +++ b/src/hotspot/share/opto/postaloc.cpp @@ -173,7 +173,7 @@ int PhaseChaitin::use_prior_register( Node *n, uint idx, Node *def, Block *curre const LRG &def_lrg = lrgs(_lrg_map.live_range_id(def)); OptoReg::Name def_reg = def_lrg.reg(); const RegMask &use_mask = n->in_RegMask(idx); - bool can_use = use_mask.member(def_reg); + bool can_use = use_mask.Member(def_reg); if (!RegMask::is_vector(def->ideal_reg())) { // Check for a copy to or from a misaligned pair. // It is workaround for a sparc with misaligned pairs. @@ -678,7 +678,7 @@ void PhaseChaitin::post_allocate_copy_removal() { int n_regs = RegMask::num_registers(def_ideal_reg, lrgs(_lrg_map.live_range_id(def))); for (int l = 1; l < n_regs; l++) { OptoReg::Name ureg_lo = OptoReg::add(ureg,-l); - bool is_adjacent = lrgs(useidx).mask().member(ureg_lo); + bool is_adjacent = lrgs(useidx).mask().Member(ureg_lo); assert(is_adjacent || OptoReg::is_reg(ureg_lo), "only registers can be non-adjacent"); if (value[ureg_lo] == nullptr && is_adjacent) { // Nearly always adjacent @@ -762,13 +762,13 @@ void PhaseChaitin::post_allocate_copy_removal() { // If the value occupies a register pair, record same info // in both registers. OptoReg::Name nreg_lo = OptoReg::add(nreg,-1); - bool is_adjacent = lrgs(lidx).mask().member(nreg_lo); + bool is_adjacent = lrgs(lidx).mask().Member(nreg_lo); assert(is_adjacent || OptoReg::is_reg(nreg_lo), "only registers can be non-adjacent"); if (!is_adjacent) { // Nearly always adjacent // Sparc occasionally has non-adjacent pairs. // Find the actual other value - RegMask tmp(lrgs(lidx).mask()); - tmp.remove(nreg); + RegMask tmp = lrgs(lidx).mask(); + tmp.Remove(nreg); nreg_lo = tmp.find_first_elem(); } if (value[nreg] != val || value[nreg_lo] != val) { diff --git a/src/hotspot/share/opto/reg_split.cpp b/src/hotspot/share/opto/reg_split.cpp index 96f87fe6947d6..327c30b152e72 100644 --- a/src/hotspot/share/opto/reg_split.cpp +++ b/src/hotspot/share/opto/reg_split.cpp @@ -476,7 +476,7 @@ bool PhaseChaitin::prompt_use( Block *b, uint lidx ) { return true; // Found 1st use! } } - if (!n->out_RegMask().is_empty()) { + if (!n->out_RegMask().is_Empty()) { return false; } } @@ -1038,7 +1038,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) { // bound use if we can't rematerialize the def, or if we need the // split to form a misaligned pair. if (!umask.is_infinite_stack() && - (int)umask.size() <= lrgs(useidx).num_regs() && + (int)umask.Size() <= lrgs(useidx).num_regs() && (!def->rematerialize() || (!is_vect && umask.is_misaligned_pair()))) { // These need a Split regardless of overlap or pressure @@ -1128,7 +1128,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) { if( n->is_SpillCopy() ) { ResourceMark rm(C->regmask_arena()); RegMask tmp_rm(umask, C->regmask_arena()); - tmp_rm.subtract(Matcher::STACK_ONLY_mask); + tmp_rm.SUBTRACT(Matcher::STACK_ONLY_mask); if( dmask.overlap(tmp_rm) ) { if( def != n->in(inpidx) ) { n->set_req(inpidx, def); diff --git a/src/hotspot/share/opto/regmask.cpp b/src/hotspot/share/opto/regmask.cpp index dcbc4dbac8e79..57cf13a8b3184 100644 --- a/src/hotspot/share/opto/regmask.cpp +++ b/src/hotspot/share/opto/regmask.cpp @@ -47,9 +47,9 @@ void OptoReg::dump(int r, outputStream *st) { //============================================================================= -const RegMask RegMask::EMPTY; +const RegMask RegMask::Empty; -const RegMask RegMask::ALL( +const RegMask RegMask::All( # define BODY(I) -1, FORALL_BODY # undef BODY @@ -126,7 +126,7 @@ void RegMask::clear_to_pairs() { } bool RegMask::is_misaligned_pair() const { - return size() == 2 && !is_aligned_pairs(); + return Size() == 2 && !is_aligned_pairs(); } bool RegMask::is_aligned_pairs() const { @@ -227,7 +227,7 @@ bool RegMask::is_bound(uint ireg) const { // for current regmask, where reg is the highest number. bool RegMask::is_valid_reg(OptoReg::Name reg, const int size) const { for (int i = 0; i < size; i++) { - if (!member(reg - i)) { + if (!Member(reg - i)) { return false; } } diff --git a/src/hotspot/share/opto/regmask.hpp b/src/hotspot/share/opto/regmask.hpp index 453fbb45d33b7..67e160940ccf2 100644 --- a/src/hotspot/share/opto/regmask.hpp +++ b/src/hotspot/share/opto/regmask.hpp @@ -299,6 +299,39 @@ class RegMask { } } + // Make us a copy of src + void copy(const RegMask& src) { + assert(_offset == src._offset, "offset mismatch"); + _hwm = src._hwm; + _lwm = src._lwm; + + // Copy base mask + memcpy(_rm_word, src._rm_word, sizeof(uintptr_t) * RM_SIZE_IN_WORDS); + _infinite_stack = src._infinite_stack; + + // Copy extension + if (src._rm_word_ext != nullptr) { + assert(src._rm_size_in_words > RM_SIZE_IN_WORDS, "sanity"); + assert(_original_ext_address == &_rm_word_ext, "clone sanity check"); + grow(src._rm_size_in_words, false); + memcpy(_rm_word_ext, src._rm_word_ext, + sizeof(uintptr_t) * (src._rm_size_in_words - RM_SIZE_IN_WORDS)); + } + + // If the source is smaller than us, we need to set the gap according to + // the sources infinite_stack flag. + if (src._rm_size_in_words < _rm_size_in_words) { + int value = 0; + if (src.is_infinite_stack()) { + value = 0xFF; + _hwm = rm_word_max_index(); + } + set_range(src._rm_size_in_words, value, _rm_size_in_words - src._rm_size_in_words); + } + + assert(valid_watermarks(), "post-condition"); + } + // Make the watermarks as tight as possible. void trim_watermarks() { if (_hwm < _lwm) { @@ -416,62 +449,31 @@ class RegMask { RegMask(OptoReg::Name reg, Arena* arena DEBUG_ONLY(COMMA bool read_only = false)) : RegMask(arena DEBUG_ONLY(COMMA read_only)) { - insert(reg); + Insert(reg); } explicit RegMask(OptoReg::Name reg) : RegMask(reg, nullptr) {} - // Make us represent the same set of registers as src. - void assignFrom(const RegMask& src) { - assert(_offset == src._offset, "offset mismatch"); - _hwm = src._hwm; - _lwm = src._lwm; - - // Copy base mask - memcpy(_rm_word, src._rm_word, sizeof(uintptr_t) * RM_SIZE_IN_WORDS); - _infinite_stack = src._infinite_stack; - - // Copy extension - if (src._rm_word_ext != nullptr) { - assert(src._rm_size_in_words > RM_SIZE_IN_WORDS, "sanity"); - assert(_original_ext_address == &_rm_word_ext, "clone sanity check"); - grow(src._rm_size_in_words, false); - memcpy(_rm_word_ext, src._rm_word_ext, - sizeof(uintptr_t) * (src._rm_size_in_words - RM_SIZE_IN_WORDS)); - } + // ---------------------------------------- + // Deep copying constructors and assignment + // ---------------------------------------- - // If the source is smaller than us, we need to set the gap according to - // the sources infinite_stack flag. - if (src._rm_size_in_words < _rm_size_in_words) { - int value = 0; - if (src.is_infinite_stack()) { - value = 0xFF; - _hwm = rm_word_max_index(); - } - set_range(src._rm_size_in_words, value, _rm_size_in_words - src._rm_size_in_words); - } - - assert(valid_watermarks(), "post-condition"); - } - - // Construct from other register mask (deep copy) and register an arena - // for potential register mask extension. Passing nullptr as arena disables - // extension. RegMask(const RegMask& rm, Arena* arena) : _arena(arena), _rm_size_in_words(RM_SIZE_IN_WORDS), _offset(rm._offset) { - assignFrom(rm); + copy(rm); } - // Copy constructor (deep copy). By default does not allow extension. - explicit RegMask(const RegMask& rm) : RegMask(rm, nullptr) {} + RegMask(const RegMask& rm) : RegMask(rm, nullptr) {} - // Disallow copy assignment (use assignFrom instead) - RegMask& operator=(const RegMask&) = delete; + RegMask& operator=(const RegMask& rm) { + copy(rm); + return *this; + } // ---------------- // End deep copying // ---------------- - bool member(OptoReg::Name reg) const { + bool Member(OptoReg::Name reg) const { reg = reg - offset_bits(); if (reg < 0) { return false; @@ -484,7 +486,7 @@ class RegMask { } // Empty mask check. Ignores registers included through the infinite_stack flag. - bool is_empty() const { + bool is_Empty() const { assert(valid_watermarks(), "sanity"); for (unsigned i = _lwm; i <= _hwm; i++) { if (rm_word(i) != 0) { @@ -640,7 +642,7 @@ class RegMask { bool is_UP() const; // Clear a register mask. Does not clear any offset. - void clear() { + void Clear() { _lwm = rm_word_max_index(); _hwm = 0; set_range(0, 0, _rm_size_in_words); @@ -649,13 +651,13 @@ class RegMask { } // Fill a register mask with 1's - void set_all() { + void Set_All() { assert(_offset == 0, "offset non-zero"); - set_all_from_offset(); + Set_All_From_Offset(); } // Fill a register mask with 1's from the current offset. - void set_all_from_offset() { + void Set_All_From_Offset() { _lwm = 0; _hwm = rm_word_max_index(); set_range(0, 0xFF, _rm_size_in_words); @@ -664,7 +666,7 @@ class RegMask { } // Fill a register mask with 1's starting from the given register. - void set_all_from(OptoReg::Name reg) { + void Set_All_From(OptoReg::Name reg) { reg = reg - offset_bits(); assert(reg != OptoReg::Bad, "sanity"); assert(reg != OptoReg::Special, "sanity"); @@ -687,7 +689,7 @@ class RegMask { } // Insert register into mask - void insert(OptoReg::Name reg) { + void Insert(OptoReg::Name reg) { reg = reg - offset_bits(); assert(reg != OptoReg::Bad, "sanity"); assert(reg != OptoReg::Special, "sanity"); @@ -704,7 +706,7 @@ class RegMask { } // Remove register from mask - void remove(OptoReg::Name reg) { + void Remove(OptoReg::Name reg) { reg = reg - offset_bits(); assert(reg >= 0, "register outside mask"); assert(reg < (int)rm_size_in_bits(), "register outside mask"); @@ -712,8 +714,8 @@ class RegMask { rm_word(r >> LogBitsPerWord) &= ~(uintptr_t(1) << (r & WORD_BIT_MASK)); } - // Or 'rm' into 'this' - void or_with(const RegMask& rm) { + // OR 'rm' into 'this' + void OR(const RegMask &rm) { assert(_offset == rm._offset, "offset mismatch"); assert(valid_watermarks() && rm.valid_watermarks(), "sanity"); grow(rm._rm_size_in_words); @@ -734,8 +736,8 @@ class RegMask { assert(valid_watermarks(), "sanity"); } - // And 'rm' into 'this' - void and_with(const RegMask& rm) { + // AND 'rm' into 'this' + void AND(const RegMask &rm) { assert(_offset == rm._offset, "offset mismatch"); assert(valid_watermarks() && rm.valid_watermarks(), "sanity"); grow(rm._rm_size_in_words); @@ -766,7 +768,7 @@ class RegMask { } // Subtract 'rm' from 'this'. - void subtract(const RegMask& rm) { + void SUBTRACT(const RegMask &rm) { assert(_offset == rm._offset, "offset mismatch"); assert(valid_watermarks() && rm.valid_watermarks(), "sanity"); grow(rm._rm_size_in_words); @@ -789,7 +791,7 @@ class RegMask { // Subtract 'rm' from 'this', but ignore everything in 'rm' that does not // overlap with us and do not modify our infinite_stack flag. Supports masks of // differing offsets. Does not support 'rm' with the infinite_stack flag set. - void subtract_inner(const RegMask& rm) { + void SUBTRACT_inner(const RegMask& rm) { assert(valid_watermarks() && rm.valid_watermarks(), "sanity"); assert(!rm.is_infinite_stack(), "not supported"); // Various translations due to differing offsets @@ -819,12 +821,12 @@ class RegMask { return false; } _offset += _rm_size_in_words; - set_all_from_offset(); + Set_All_From_Offset(); return true; } // Compute size of register mask: number of bits - uint size() const { + uint Size() const { uint sum = 0; assert(valid_watermarks(), "sanity"); for (unsigned i = _lwm; i <= _hwm; i++) { @@ -893,8 +895,8 @@ class RegMask { void dump_hex(outputStream* st = tty) const; // Print a mask (raw hex) #endif - static const RegMask EMPTY; // Common empty mask - static const RegMask ALL; // Common all mask + static const RegMask Empty; // Common empty mask + static const RegMask All; // Common all mask bool can_represent(OptoReg::Name reg, unsigned int size = 1) const { reg = reg - offset_bits(); diff --git a/src/hotspot/share/opto/rootnode.cpp b/src/hotspot/share/opto/rootnode.cpp index 60167c5436a13..4ced13abdb1f6 100644 --- a/src/hotspot/share/opto/rootnode.cpp +++ b/src/hotspot/share/opto/rootnode.cpp @@ -88,5 +88,5 @@ const Type* HaltNode::Value(PhaseGVN* phase) const { } const RegMask &HaltNode::out_RegMask() const { - return RegMask::EMPTY; + return RegMask::Empty; } diff --git a/src/hotspot/share/opto/superword.cpp b/src/hotspot/share/opto/superword.cpp index 6ab1ff37de9fd..c0f005048ec66 100644 --- a/src/hotspot/share/opto/superword.cpp +++ b/src/hotspot/share/opto/superword.cpp @@ -2500,8 +2500,6 @@ static bool can_subword_truncate(Node* in, const Type* type) { case Op_RotateRight: case Op_RotateLeft: case Op_PopCountI: - case Op_ReverseBytesS: - case Op_ReverseBytesUS: case Op_ReverseBytesI: case Op_ReverseI: case Op_CountLeadingZerosI: diff --git a/src/hotspot/share/prims/jvmtiAgentList.cpp b/src/hotspot/share/prims/jvmtiAgentList.cpp index 41fc9c0f3594c..8da5b75be4611 100644 --- a/src/hotspot/share/prims/jvmtiAgentList.cpp +++ b/src/hotspot/share/prims/jvmtiAgentList.cpp @@ -196,11 +196,6 @@ void JvmtiAgentList::load_xrun_agents() { // Invokes Agent_OnAttach for agents loaded dynamically during runtime. void JvmtiAgentList::load_agent(const char* agent_name, bool is_absolute_path, const char* options, outputStream* st) { - if (JvmtiEnvBase::get_phase() != JVMTI_PHASE_LIVE) { - st->print_cr("Dynamic agent loading is only permitted in the live phase"); - return; - } - JvmtiAgent* const agent = new JvmtiAgent(agent_name, options, is_absolute_path, /* dynamic agent */ true); if (agent->load(st)) { add(agent); diff --git a/src/hotspot/share/prims/jvmtiExport.cpp b/src/hotspot/share/prims/jvmtiExport.cpp index 0884fce2ff7ac..fa6ede86cd9a4 100644 --- a/src/hotspot/share/prims/jvmtiExport.cpp +++ b/src/hotspot/share/prims/jvmtiExport.cpp @@ -879,6 +879,7 @@ class JvmtiClassFileLoadHookPoster : public StackObj { JvmtiThreadState * _state; Klass* _class_being_redefined; JvmtiClassLoadKind _load_kind; + bool _has_been_modified; public: inline JvmtiClassFileLoadHookPoster(Symbol* h_name, Handle class_loader, @@ -895,6 +896,7 @@ class JvmtiClassFileLoadHookPoster : public StackObj { _curr_data = *data_ptr; _curr_env = nullptr; _cached_class_file_ptr = cache_ptr; + _has_been_modified = false; _state = JvmtiExport::get_jvmti_thread_state(_thread); if (_state != nullptr) { @@ -933,6 +935,8 @@ class JvmtiClassFileLoadHookPoster : public StackObj { copy_modified_data(); } + bool has_been_modified() { return _has_been_modified; } + private: void post_all_envs() { if (_load_kind != jvmti_class_load_kind_retransform) { @@ -979,6 +983,7 @@ class JvmtiClassFileLoadHookPoster : public StackObj { } if (new_data != nullptr) { // this agent has modified class data. + _has_been_modified = true; if (caching_needed && *_cached_class_file_ptr == nullptr) { // data has been changed by the new retransformable agent // and it hasn't already been cached, cache it @@ -1053,18 +1058,18 @@ bool JvmtiExport::_should_post_class_file_load_hook = false; int JvmtiExport::_should_notify_object_alloc = 0; // this entry is for class file load hook on class load, redefine and retransform -void JvmtiExport::post_class_file_load_hook(Symbol* h_name, +bool JvmtiExport::post_class_file_load_hook(Symbol* h_name, Handle class_loader, Handle h_protection_domain, unsigned char **data_ptr, unsigned char **end_ptr, JvmtiCachedClassFileData **cache_ptr) { if (JvmtiEnv::get_phase() < JVMTI_PHASE_PRIMORDIAL) { - return; + return false; } if (JavaThread::current()->should_hide_jvmti_events()) { - return; + return false; } JvmtiClassFileLoadHookPoster poster(h_name, class_loader, @@ -1072,6 +1077,7 @@ void JvmtiExport::post_class_file_load_hook(Symbol* h_name, data_ptr, end_ptr, cache_ptr); poster.post(); + return poster.has_been_modified(); } void JvmtiExport::report_unsupported(bool on) { diff --git a/src/hotspot/share/prims/jvmtiExport.hpp b/src/hotspot/share/prims/jvmtiExport.hpp index 8906d6b81df6c..062057c70abf8 100644 --- a/src/hotspot/share/prims/jvmtiExport.hpp +++ b/src/hotspot/share/prims/jvmtiExport.hpp @@ -377,10 +377,11 @@ class JvmtiExport : public AllStatic { static bool is_early_phase() NOT_JVMTI_RETURN_(false); static bool has_early_class_hook_env() NOT_JVMTI_RETURN_(false); static bool has_early_vmstart_env() NOT_JVMTI_RETURN_(false); - static void post_class_file_load_hook(Symbol* h_name, Handle class_loader, + // Return true if the class was modified by the hook. + static bool post_class_file_load_hook(Symbol* h_name, Handle class_loader, Handle h_protection_domain, unsigned char **data_ptr, unsigned char **end_ptr, - JvmtiCachedClassFileData **cache_ptr) NOT_JVMTI_RETURN; + JvmtiCachedClassFileData **cache_ptr) NOT_JVMTI_RETURN_(false); static void post_native_method_bind(Method* method, address* function_ptr) NOT_JVMTI_RETURN; static void post_compiled_method_load(JvmtiEnv* env, nmethod *nm) NOT_JVMTI_RETURN; static void post_compiled_method_load(nmethod *nm) NOT_JVMTI_RETURN; diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index 0d92f22af79d4..8b703cb442a74 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -548,7 +548,6 @@ static SpecialFlag const special_jvm_flags[] = { { "ZGenerational", JDK_Version::jdk(23), JDK_Version::jdk(24), JDK_Version::undefined() }, { "ZMarkStackSpaceLimit", JDK_Version::undefined(), JDK_Version::jdk(25), JDK_Version::undefined() }, { "G1UpdateBufferSize", JDK_Version::undefined(), JDK_Version::jdk(26), JDK_Version::jdk(27) }, - { "ShenandoahPacing", JDK_Version::jdk(25), JDK_Version::jdk(26), JDK_Version::jdk(27) }, #if defined(AARCH64) { "NearCpool", JDK_Version::undefined(), JDK_Version::jdk(25), JDK_Version::undefined() }, #endif @@ -1521,12 +1520,6 @@ void Arguments::set_heap_size() { !FLAG_IS_DEFAULT(InitialRAMPercentage) || !FLAG_IS_DEFAULT(MaxRAM); - if (CompilerConfig::should_set_client_emulation_mode_flags() && - FLAG_IS_DEFAULT(MaxRAM)) { - // Reduce the maximum available memory if client emulation mode is enabled. - FLAG_SET_DEFAULT(MaxRAM, 1ULL*G); - } - if (has_ram_limit) { if (!FLAG_IS_DEFAULT(MaxRAM)) { // The user has configured MaxRAM, use that instead of physical memory diff --git a/src/hotspot/share/runtime/continuationEntry.hpp b/src/hotspot/share/runtime/continuationEntry.hpp index 490293f5b118f..8361f2f912be6 100644 --- a/src/hotspot/share/runtime/continuationEntry.hpp +++ b/src/hotspot/share/runtime/continuationEntry.hpp @@ -39,7 +39,6 @@ class RegisterMap; // Metadata stored in the continuation entry frame class ContinuationEntry { - friend class VMStructs; friend class JVMCIVMStructs; ContinuationEntryPD _pd; #ifdef ASSERT diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp index daafcaea61bfe..853c6554022f9 100644 --- a/src/hotspot/share/runtime/deoptimization.cpp +++ b/src/hotspot/share/runtime/deoptimization.cpp @@ -1804,11 +1804,10 @@ void Deoptimization::deoptimize(JavaThread* thread, frame fr, DeoptReason reason deoptimize_single_frame(thread, fr, reason); } -address Deoptimization::deoptimize_for_missing_exception_handler(nmethod* nm, bool make_not_entrant) { +#if INCLUDE_JVMCI +address Deoptimization::deoptimize_for_missing_exception_handler(nmethod* nm) { // there is no exception handler for this pc => deoptimize - if (make_not_entrant) { - nm->make_not_entrant(nmethod::InvalidationReason::MISSING_EXCEPTION_HANDLER); - } + nm->make_not_entrant(nmethod::InvalidationReason::MISSING_EXCEPTION_HANDLER); // Use Deoptimization::deoptimize for all of its side-effects: // gathering traps statistics, logging... @@ -1822,15 +1821,6 @@ address Deoptimization::deoptimize_for_missing_exception_handler(nmethod* nm, bo frame runtime_frame = thread->last_frame(); frame caller_frame = runtime_frame.sender(®_map); assert(caller_frame.cb()->as_nmethod_or_null() == nm, "expect top frame compiled method"); - - Deoptimization::deoptimize(thread, caller_frame, Deoptimization::Reason_not_compiled_exception_handler); - - if (!nm->is_compiled_by_jvmci()) { - return SharedRuntime::deopt_blob()->unpack_with_exception_in_tls(); - } - -#if INCLUDE_JVMCI - // JVMCI support vframe* vf = vframe::new_vframe(&caller_frame, ®_map, thread); compiledVFrame* cvf = compiledVFrame::cast(vf); ScopeDesc* imm_scope = cvf->scope(); @@ -1846,15 +1836,16 @@ address Deoptimization::deoptimize_for_missing_exception_handler(nmethod* nm, bo } } + Deoptimization::deoptimize(thread, caller_frame, Deoptimization::Reason_not_compiled_exception_handler); MethodData* trap_mdo = get_method_data(thread, methodHandle(thread, nm->method()), true); if (trap_mdo != nullptr) { trap_mdo->inc_trap_count(Deoptimization::Reason_not_compiled_exception_handler); } -#endif return SharedRuntime::deopt_blob()->unpack_with_exception_in_tls(); } +#endif void Deoptimization::deoptimize_frame_internal(JavaThread* thread, intptr_t* id, DeoptReason reason) { assert(thread == Thread::current() || @@ -2757,10 +2748,10 @@ const char* Deoptimization::_trap_reason_name[] = { "unstable_if", "unstable_fused_if", "receiver_constraint", - "not_compiled_exception_handler", "short_running_loop" JVMCI_ONLY("_or_aliasing"), #if INCLUDE_JVMCI "transfer_to_interpreter", + "not_compiled_exception_handler", "unresolved", "jsr_mismatch", #endif diff --git a/src/hotspot/share/runtime/deoptimization.hpp b/src/hotspot/share/runtime/deoptimization.hpp index d168d9c8af682..5d97e2056adcc 100644 --- a/src/hotspot/share/runtime/deoptimization.hpp +++ b/src/hotspot/share/runtime/deoptimization.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -117,11 +117,11 @@ class Deoptimization : AllStatic { Reason_unstable_if, // a branch predicted always false was taken Reason_unstable_fused_if, // fused two ifs that had each one untaken branch. One is now taken. Reason_receiver_constraint, // receiver subtype check failed - Reason_not_compiled_exception_handler, // missing compiled exception handler Reason_short_running_long_loop, // profile reports loop runs for small number of iterations #if INCLUDE_JVMCI Reason_aliasing = Reason_short_running_long_loop, // optimistic assumption about aliasing failed Reason_transfer_to_interpreter, // explicit transferToInterpreter() + Reason_not_compiled_exception_handler, Reason_unresolved, Reason_jsr_mismatch, #endif @@ -184,8 +184,8 @@ class Deoptimization : AllStatic { // Deoptimizes a frame lazily. Deopt happens on return to the frame. static void deoptimize(JavaThread* thread, frame fr, DeoptReason reason = Reason_constraint); - static address deoptimize_for_missing_exception_handler(nmethod* nm, bool make_not_entrant); #if INCLUDE_JVMCI + static address deoptimize_for_missing_exception_handler(nmethod* nm); static oop get_cached_box(AutoBoxObjectValue* bv, frame* fr, RegisterMap* reg_map, bool& cache_init_error, TRAPS); #endif diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index 238517197b2c4..513edaf658816 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -502,7 +502,7 @@ const int ObjectAlignmentInBytes = 8; "If > 0, provokes an error after VM initialization; the value " \ "determines which error to provoke. See controlled_crash() " \ "in vmError.cpp.") \ - range(0, 18) \ + range(0, 17) \ \ develop(uint, TestCrashInErrorHandler, 0, \ "If > 0, provokes an error inside VM error handler (a secondary " \ diff --git a/src/hotspot/share/runtime/javaThread.cpp b/src/hotspot/share/runtime/javaThread.cpp index 36544cf1118ea..8bb8095878f3a 100644 --- a/src/hotspot/share/runtime/javaThread.cpp +++ b/src/hotspot/share/runtime/javaThread.cpp @@ -535,6 +535,7 @@ JavaThread::JavaThread(MemTag mem_tag) : set_requires_cross_modify_fence(false); pd_initialize(); + assert(deferred_card_mark().is_empty(), "Default MemRegion ctor"); } JavaThread* JavaThread::create_attaching_thread() { @@ -1358,6 +1359,9 @@ void JavaThread::pop_jni_handle_block() { } void JavaThread::oops_do_no_frames(OopClosure* f, NMethodClosure* cf) { + // Verify that the deferred card marks have been flushed. + assert(deferred_card_mark().is_empty(), "Should be empty during GC"); + // Traverse the GCHandles Thread::oops_do_no_frames(f, cf); diff --git a/src/hotspot/share/runtime/javaThread.hpp b/src/hotspot/share/runtime/javaThread.hpp index a6a00bfbd033e..c8be1594a69fa 100644 --- a/src/hotspot/share/runtime/javaThread.hpp +++ b/src/hotspot/share/runtime/javaThread.hpp @@ -149,6 +149,11 @@ class JavaThread: public Thread { oop _vm_result_oop; // oop result is GC-preserved Metadata* _vm_result_metadata; // non-oop result + // See ReduceInitialCardMarks: this holds the precise space interval of + // the most recent slow path allocation for which compiled code has + // elided card-marks for performance along the fast-path. + MemRegion _deferred_card_mark; + ObjectMonitor* volatile _current_pending_monitor; // ObjectMonitor this thread is waiting to lock bool _current_pending_monitor_is_from_java; // locking is from Java code ObjectMonitor* volatile _current_waiting_monitor; // ObjectMonitor on which this thread called Object.wait() @@ -771,6 +776,9 @@ class JavaThread: public Thread { void set_vm_result_metadata(Metadata* x) { _vm_result_metadata = x; } + MemRegion deferred_card_mark() const { return _deferred_card_mark; } + void set_deferred_card_mark(MemRegion mr) { _deferred_card_mark = mr; } + // Is thread in scope of an InternalOOMEMark? bool is_in_internal_oome_mark() const { return _is_in_internal_oome_mark; } void set_is_in_internal_oome_mark(bool b) { _is_in_internal_oome_mark = b; } diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp index f6d569b1b7a50..142324fec7a80 100644 --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -1863,10 +1863,10 @@ void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) { // could be profitable. // // TODO-FIXME: change the following logic to a loop of the form - // while (!timeout && !interrupted && node.TState == TS_WAIT) park() + // while (!timeout && !interrupted && _notified == 0) park() int ret = OS_OK; - bool was_notified = false; + int WasNotified = 0; // Need to check interrupt state whilst still _thread_in_vm bool interrupted = interruptible && current->is_interrupted(false); @@ -1882,7 +1882,7 @@ void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) { ThreadBlockInVMPreprocess tbivs(current, csos, true /* allow_suspend */); if (interrupted || HAS_PENDING_EXCEPTION) { // Intentionally empty - } else if (node.TState == ObjectWaiter::TS_WAIT) { + } else if (!node._notified) { if (millis <= 0) { current->_ParkEvent->park(); } else { @@ -1910,6 +1910,7 @@ void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) { Thread::SpinAcquire(&_wait_set_lock); if (node.TState == ObjectWaiter::TS_WAIT) { dequeue_specific_waiter(&node); // unlink from wait_set + assert(!node._notified, "invariant"); node.TState = ObjectWaiter::TS_RUN; } Thread::SpinRelease(&_wait_set_lock); @@ -1922,7 +1923,7 @@ void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) { guarantee(node.TState != ObjectWaiter::TS_WAIT, "invariant"); OrderAccess::loadload(); if (has_successor(current)) clear_successor(); - was_notified = node.TState == ObjectWaiter::TS_ENTER; + WasNotified = node._notified; // Reentry phase -- reacquire the monitor. // re-enter contended monitor after object.wait(). @@ -1935,7 +1936,7 @@ void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) { if (JvmtiExport::should_post_monitor_waited()) { JvmtiExport::post_monitor_waited(current, this, ret == OS_TIMEOUT); - if (was_notified && has_successor(current)) { + if (node._notified && has_successor(current)) { // In this part of the monitor wait-notify-reenter protocol it // is possible (and normal) for another thread to do a fastpath // monitor enter-exit while this thread is still trying to get @@ -2002,7 +2003,7 @@ void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) { } // check if the notification happened - if (!was_notified) { + if (!WasNotified) { // no, it could be timeout or Thread.interrupt() or both // check for interrupt event, otherwise it is timeout if (interruptible && current->is_interrupted(true) && !HAS_PENDING_EXCEPTION) { @@ -2025,6 +2026,7 @@ bool ObjectMonitor::notify_internal(JavaThread* current) { ObjectWaiter* iterator = dequeue_waiter(); if (iterator != nullptr) { guarantee(iterator->TState == ObjectWaiter::TS_WAIT, "invariant"); + guarantee(!iterator->_notified, "invariant"); if (iterator->is_vthread()) { oop vthread = iterator->vthread(); @@ -2046,6 +2048,7 @@ bool ObjectMonitor::notify_internal(JavaThread* current) { inc_unmounted_vthreads(); } + iterator->_notified = true; iterator->_notifier_tid = JFR_THREAD_ID(current); did_notify = true; add_to_entry_list(current, iterator); @@ -2207,6 +2210,7 @@ bool ObjectMonitor::vthread_wait_reenter(JavaThread* current, ObjectWaiter* node Thread::SpinAcquire(&_wait_set_lock); if (node->TState == ObjectWaiter::TS_WAIT) { dequeue_specific_waiter(node); // unlink from wait_set + assert(!node->_notified, "invariant"); node->TState = ObjectWaiter::TS_RUN; } Thread::SpinRelease(&_wait_set_lock); @@ -2512,6 +2516,7 @@ ObjectWaiter::ObjectWaiter(JavaThread* current) { _notifier_tid = 0; _recursions = 0; TState = TS_RUN; + _notified = false; _is_wait = false; _at_reenter = false; _interrupted = false; diff --git a/src/hotspot/share/runtime/objectMonitor.hpp b/src/hotspot/share/runtime/objectMonitor.hpp index 77919d9995586..058e0317ec189 100644 --- a/src/hotspot/share/runtime/objectMonitor.hpp +++ b/src/hotspot/share/runtime/objectMonitor.hpp @@ -52,6 +52,7 @@ class ObjectWaiter : public CHeapObj { uint64_t _notifier_tid; int _recursions; volatile TStates TState; + volatile bool _notified; bool _is_wait; bool _at_reenter; bool _interrupted; @@ -66,8 +67,9 @@ class ObjectWaiter : public CHeapObj { uint8_t state() const { return TState; } ObjectMonitor* monitor() const { return _monitor; } bool is_wait() const { return _is_wait; } + bool notified() const { return _notified; } bool at_reenter() const { return _at_reenter; } - bool at_monitorenter() const { return !_is_wait || TState != TS_WAIT; } + bool at_monitorenter() const { return !_is_wait || _at_reenter || _notified; } oop vthread() const; void wait_reenter_begin(ObjectMonitor *mon); void wait_reenter_end(ObjectMonitor *mon); diff --git a/src/hotspot/share/runtime/perfMemory.cpp b/src/hotspot/share/runtime/perfMemory.cpp index 9594149333e6e..a75a41e95a94c 100644 --- a/src/hotspot/share/runtime/perfMemory.cpp +++ b/src/hotspot/share/runtime/perfMemory.cpp @@ -114,7 +114,9 @@ void PerfMemory::initialize() { // the warning is issued only in debug mode in order to avoid // additional output to the stdout or stderr output streams. // - log_debug(perf)("could not create PerfData Memory region, reverting to malloc"); + if (PrintMiscellaneous && Verbose) { + warning("Could not create PerfData Memory region, reverting to malloc"); + } _prologue = NEW_C_HEAP_OBJ(PerfDataPrologue, mtInternal); } @@ -248,7 +250,10 @@ char* PerfMemory::get_perfdata_file_path() { if(!Arguments::copy_expand_pid(PerfDataSaveFile, strlen(PerfDataSaveFile), dest_file, JVM_MAXPATHLEN)) { FREE_C_HEAP_ARRAY(char, dest_file); - log_debug(perf)("invalid performance data file path name specified, fall back to a default name"); + if (PrintMiscellaneous && Verbose) { + warning("Invalid performance data file path name specified, "\ + "fall back to a default name"); + } } else { return dest_file; } diff --git a/src/hotspot/share/runtime/serviceThread.cpp b/src/hotspot/share/runtime/serviceThread.cpp index 03168842e3634..9a0bfe03ac3be 100644 --- a/src/hotspot/share/runtime/serviceThread.cpp +++ b/src/hotspot/share/runtime/serviceThread.cpp @@ -45,7 +45,7 @@ #include "services/lowMemoryDetector.hpp" #include "services/threadIdTable.hpp" -JavaThread* ServiceThread::_instance = nullptr; +DEBUG_ONLY(JavaThread* ServiceThread::_instance = nullptr;) JvmtiDeferredEvent* ServiceThread::_jvmti_event = nullptr; // The service thread has it's own static deferred event queue. // Events can be posted before JVMTI vm_start, so it's too early to call JvmtiThreadState::state_for @@ -62,7 +62,7 @@ void ServiceThread::initialize() { JavaThread::vm_exit_on_osthread_failure(thread); JavaThread::start_internal_daemon(THREAD, thread, thread_oop, NearMaxPriority); - _instance = thread; + DEBUG_ONLY(_instance = thread;) } static void cleanup_oopstorages() { diff --git a/src/hotspot/share/runtime/serviceThread.hpp b/src/hotspot/share/runtime/serviceThread.hpp index cfce8603cd5a2..f65847ece0069 100644 --- a/src/hotspot/share/runtime/serviceThread.hpp +++ b/src/hotspot/share/runtime/serviceThread.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,7 +35,7 @@ class JvmtiDeferredEvent; class ServiceThread : public JavaThread { private: - static JavaThread* _instance; + DEBUG_ONLY(static JavaThread* _instance;) static JvmtiDeferredEvent* _jvmti_event; static JvmtiDeferredEventQueue _jvmti_service_queue; @@ -44,7 +44,6 @@ class ServiceThread : public JavaThread { public: static void initialize(); - static bool has_started() { return _instance != nullptr; } // Hide this thread from external view. bool is_hidden_from_external_view() const { return true; } diff --git a/src/hotspot/share/runtime/sharedRuntime.cpp b/src/hotspot/share/runtime/sharedRuntime.cpp index 35bc3f5f1beaf..efc47dd11c643 100644 --- a/src/hotspot/share/runtime/sharedRuntime.cpp +++ b/src/hotspot/share/runtime/sharedRuntime.cpp @@ -791,8 +791,7 @@ address SharedRuntime::compute_compiled_exc_handler(nmethod* nm, address ret_pc, if (t != nullptr) { return nm->code_begin() + t->pco(); } else { - bool make_not_entrant = true; - return Deoptimization::deoptimize_for_missing_exception_handler(nm, make_not_entrant); + return Deoptimization::deoptimize_for_missing_exception_handler(nm); } } #endif // INCLUDE_JVMCI @@ -848,15 +847,6 @@ address SharedRuntime::compute_compiled_exc_handler(nmethod* nm, address ret_pc, ExceptionHandlerTable table(nm); HandlerTableEntry *t = table.entry_for(catch_pco, handler_bci, scope_depth); - - // If the compiler did not anticipate a recursive exception, resulting in an exception - // thrown from the catch bci, then the compiled exception handler might be missing. - // This is rare. Just deoptimize and let the interpreter handle it. - if (t == nullptr && recursive_exception_occurred) { - bool make_not_entrant = false; - return Deoptimization::deoptimize_for_missing_exception_handler(nm, make_not_entrant); - } - if (t == nullptr && (nm->is_compiled_by_c1() || handler_bci != -1)) { // Allow abbreviated catch tables. The idea is to allow a method // to materialize its exceptions without committing to the exact diff --git a/src/hotspot/share/runtime/sharedRuntime.hpp b/src/hotspot/share/runtime/sharedRuntime.hpp index f4ff51504f0e5..93cd92b3a32df 100644 --- a/src/hotspot/share/runtime/sharedRuntime.hpp +++ b/src/hotspot/share/runtime/sharedRuntime.hpp @@ -384,6 +384,10 @@ class SharedRuntime: AllStatic { // deopt blob static void generate_deopt_blob(void); + static bool handle_ic_miss_helper_internal(Handle receiver, nmethod* caller_nm, const frame& caller_frame, + methodHandle callee_method, Bytecodes::Code bc, CallInfo& call_info, + bool& needs_ic_stub_refill, TRAPS); + public: static DeoptimizationBlob* deopt_blob(void) { return _deopt_blob; } @@ -545,6 +549,7 @@ class SharedRuntime: AllStatic { // A compiled caller has just called the interpreter, but compiled code // exists. Patch the caller so he no longer calls into the interpreter. static void fixup_callers_callsite(Method* moop, address ret_pc); + static bool should_fixup_call_destination(address destination, address entry_point, address caller_pc, Method* moop, CodeBlob* cb); // Slow-path Locking and Unlocking static void complete_monitor_locking_C(oopDesc* obj, BasicLock* lock, JavaThread* current); diff --git a/src/hotspot/share/runtime/threads.cpp b/src/hotspot/share/runtime/threads.cpp index 299905ff0a2a3..ffe1a86cda57e 100644 --- a/src/hotspot/share/runtime/threads.cpp +++ b/src/hotspot/share/runtime/threads.cpp @@ -97,7 +97,6 @@ #include "runtime/trimNativeHeap.hpp" #include "runtime/vm_version.hpp" #include "runtime/vmOperations.hpp" -#include "sanitizers/address.hpp" #include "services/attachListener.hpp" #include "services/management.hpp" #include "services/threadIdTable.hpp" @@ -344,11 +343,6 @@ static void call_initPhase3(TRAPS) { void Threads::initialize_java_lang_classes(JavaThread* main_thread, TRAPS) { TraceTime timer("Initialize java.lang classes", TRACETIME_LOG(Info, startuptime)); - // This is before the execution of the very first Java bytecode. - if (CDSConfig::is_using_aot_linked_classes()) { - AOTLinkedClassBulkLoader::link_classes(THREAD); - } - initialize_class(vmSymbols::java_lang_String(), CHECK); // Inject CompactStrings value after the static initializers for String ran. @@ -703,10 +697,6 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { // No more stub generation allowed after that point. StubCodeDesc::freeze(); -#ifdef ADDRESS_SANITIZER - Asan::initialize(); -#endif - // Set flag that basic initialization has completed. Used by exceptions and various // debug stuff, that does not work until all basic classes have been initialized. set_init_completed(); @@ -752,10 +742,6 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { // and other cleanups. Needs to start before the compilers start posting events. ServiceThread::initialize(); - if (CDSConfig::is_using_aot_linked_classes()) { - nmethod::post_delayed_compiled_method_load_events(); - } - // Start the monitor deflation thread: MonitorDeflationThread::initialize(); @@ -788,7 +774,7 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { if (CDSConfig::is_using_aot_linked_classes()) { SystemDictionary::restore_archived_method_handle_intrinsics(); - AOTLinkedClassBulkLoader::init_javabase_classes(THREAD); + AOTLinkedClassBulkLoader::link_or_init_javabase_classes(THREAD); } // Start string deduplication thread if requested. @@ -807,7 +793,7 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { call_initPhase2(CHECK_JNI_ERR); if (CDSConfig::is_using_aot_linked_classes()) { - AOTLinkedClassBulkLoader::init_non_javabase_classes(THREAD); + AOTLinkedClassBulkLoader::link_or_init_non_javabase_classes(THREAD); } #ifndef PRODUCT HeapShared::initialize_test_class_from_archive(THREAD); diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index 85f921ef3e33c..dee0a5d4eb7d4 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -616,7 +616,6 @@ nonstatic_field(JavaThread, _active_handles, JNIHandleBlock*) \ nonstatic_field(JavaThread, _monitor_owner_id, int64_t) \ volatile_nonstatic_field(JavaThread, _terminated, JavaThread::TerminatedTypes) \ - nonstatic_field(JavaThread, _cont_entry, ContinuationEntry*) \ nonstatic_field(Thread, _osthread, OSThread*) \ \ /************/ \ @@ -797,8 +796,7 @@ nonstatic_field(Mutex, _name, const char*) \ static_field(Mutex, _mutex_array, Mutex**) \ static_field(Mutex, _num_mutex, int) \ - volatile_nonstatic_field(Mutex, _owner, Thread*) \ - static_field(ContinuationEntry, _return_pc, address) + volatile_nonstatic_field(Mutex, _owner, Thread*) //-------------------------------------------------------------------------------- // VM_TYPES @@ -1272,7 +1270,6 @@ declare_toplevel_type(FileMapHeader) \ declare_toplevel_type(CDSFileMapRegion) \ declare_toplevel_type(UpcallStub::FrameData) \ - declare_toplevel_type(ContinuationEntry) \ \ /************/ \ /* GC types */ \ @@ -1581,8 +1578,8 @@ declare_constant(Deoptimization::Reason_unstable_if) \ declare_constant(Deoptimization::Reason_unstable_fused_if) \ declare_constant(Deoptimization::Reason_receiver_constraint) \ - declare_constant(Deoptimization::Reason_not_compiled_exception_handler) \ NOT_ZERO(JVMCI_ONLY(declare_constant(Deoptimization::Reason_transfer_to_interpreter))) \ + NOT_ZERO(JVMCI_ONLY(declare_constant(Deoptimization::Reason_not_compiled_exception_handler))) \ NOT_ZERO(JVMCI_ONLY(declare_constant(Deoptimization::Reason_unresolved))) \ NOT_ZERO(JVMCI_ONLY(declare_constant(Deoptimization::Reason_jsr_mismatch))) \ declare_constant(Deoptimization::Reason_tenured) \ diff --git a/src/hotspot/share/sanitizers/address.cpp b/src/hotspot/share/sanitizers/address.cpp deleted file mode 100644 index b050039b1b821..0000000000000 --- a/src/hotspot/share/sanitizers/address.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * 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. - * - */ - -#ifdef ADDRESS_SANITIZER - -#include "logging/log.hpp" -#include "sanitizers/address.hpp" -#include "utilities/globalDefinitions.hpp" -#include "utilities/vmError.hpp" - -#include -#include - -typedef void (*callback_setter_t) (void (*callback)(const char *)); -static callback_setter_t g_callback_setter = nullptr; -static const char* g_report = nullptr; - -extern "C" void asan_error_callback(const char* report_text) { - // Please keep things very short and simple here and use as little - // as possible of any hotspot infrastructure. However shaky the JVM, - // we should always at least get the ASAN report on stderr. - - // Note: this is threadsafe since ASAN synchronizes error reports - g_report = report_text; - - // First, print off the bare error to stderr - fprintf(stderr, "JVM caught ASAN Error\n"); - fprintf(stderr, "%s\n", report_text); - - // Then, let normal JVM error handling run its due course. - fatal("ASAN Error"); -} - -void Asan::initialize() { - - // For documentation of __asan_set_error_report_callback() see asan_interface.h . - g_callback_setter = (callback_setter_t) dlsym(RTLD_DEFAULT, "__asan_set_error_report_callback"); - if (g_callback_setter == nullptr) { - log_info(asan)("*** Failed to install JVM callback for ASAN. ASAN errors will not generate hs-err files. ***"); - return; - } - - g_callback_setter(asan_error_callback); - log_info(asan)("JVM callback for ASAN errors successfully installed"); - - // Controlling core dump behavior: - // - // In hotspot, CreateCoredumpOnCrash decides whether to create a core dump (on Posix, whether to - // end the process with abort(3) or exit(3)). - // - // Core generation in the default ASAN reporter is controlled by two options: - // - "abort_on_error=0" (default) - end with exit(3), "abort_on_error=1" end with abort(3) - // - "disable_coredump=1" (default) disables cores by imposing a near-zero core soft limit. - // By default both options are set to prevent cores. That default makes sense since ASAN cores - // can get very large (due to the shadow map) and very numerous (ASAN is typically ran for - // large-scale integration tests, not targeted micro-tests). - // - // In hotspot ASAN builds, we replace the default ASAN reporter. The soft limit imposed by - // "disable_coredump=1" is still in effect. But "abort_on_error" is not honored. Since we'd - // like to exhibit exactly the same behavior as the standard ASAN error reporter, we disable - // core files if ASAN would inhibit them (we just switch off CreateCoredumpOnCrash). - // - // Thus: - // abort_on_error disable_coredump core file? - // 0 0 No (enforced by ergo-setting CreateCoredumpOnCrash=0) - // (*) 0 1 No (enforced by ASAN-imposed soft limit) - // 1 0 Yes, unless -XX:-CreateCoredumpOnCrash set on command line - // 1 1 No (enforced by ASAN-imposed soft limit) - // (*) is the default if no ASAN options are specified. - - const char* const asan_options = getenv("ASAN_OPTIONS"); - const bool asan_inhibits_cores = (asan_options == nullptr) || - (::strstr(asan_options, "abort_on_error=1") == nullptr) || - (::strstr(asan_options, "disable_coredump=0") == nullptr); - if (asan_inhibits_cores) { - if (CreateCoredumpOnCrash) { - log_info(asan)("CreateCoredumpOnCrash overruled by%s asan options. Core generation disabled.", - asan_options != nullptr ? "" : " default setting for"); - log_info(asan)("Use 'ASAN_OPTIONS=abort_on_error=1:disable_coredump=0:unmap_shadow_on_exit=1' " - "to enable core generation."); - } - FLAG_SET_ERGO(CreateCoredumpOnCrash, false); - } -} - -bool Asan::had_error() { - return g_report != nullptr; -} - -void Asan::report(outputStream* st) { - if (had_error()) { - // Use raw print here to avoid truncation. - st->print_raw(g_report); - st->cr(); - st->cr(); - } -} - -#endif // ADDRESS_SANITIZER diff --git a/src/hotspot/share/sanitizers/address.hpp b/src/hotspot/share/sanitizers/address.hpp index 109aa59dac07b..5186053f1c9e4 100644 --- a/src/hotspot/share/sanitizers/address.hpp +++ b/src/hotspot/share/sanitizers/address.hpp @@ -26,8 +26,6 @@ #define SHARE_SANITIZERS_ADDRESS_HPP #ifdef ADDRESS_SANITIZER -#include "memory/allStatic.hpp" - #include #endif @@ -76,14 +74,4 @@ } while (false) #endif -class outputStream; - -#ifdef ADDRESS_SANITIZER -struct Asan : public AllStatic { - static void initialize(); - static bool had_error(); - static void report(outputStream* st); -}; -#endif - #endif // SHARE_SANITIZERS_ADDRESS_HPP diff --git a/src/hotspot/share/services/diagnosticCommand.hpp b/src/hotspot/share/services/diagnosticCommand.hpp index 2364b0ce4cd72..001d89a5aef22 100644 --- a/src/hotspot/share/services/diagnosticCommand.hpp +++ b/src/hotspot/share/services/diagnosticCommand.hpp @@ -356,9 +356,7 @@ class ThreadDumpDCmd : public DCmdWithParser { ThreadDumpDCmd(outputStream* output, bool heap); static const char* name() { return "Thread.print"; } static const char* description() { - return "Print all platform threads, and mounted virtual threads, " - "with stack traces. The Thread.dump_to_file command will " - "print all threads to a file."; + return "Print all threads with stacktraces."; } static const char* impact() { return "Medium: Depends on the number of threads."; @@ -770,8 +768,7 @@ class ThreadDumpToFileDCmd : public DCmdWithParser { return "Thread.dump_to_file"; } static const char *description() { - return "Dump all threads, with stack traces, " - "to a file in plain text or JSON format."; + return "Dump threads, with stack traces, to a file in plain text or JSON format."; } static const char* impact() { return "Medium: Depends on the number of threads."; diff --git a/src/hotspot/share/utilities/globalDefinitions.hpp b/src/hotspot/share/utilities/globalDefinitions.hpp index 68900f8bc8693..51ea80a0150af 100644 --- a/src/hotspot/share/utilities/globalDefinitions.hpp +++ b/src/hotspot/share/utilities/globalDefinitions.hpp @@ -26,7 +26,6 @@ #define SHARE_UTILITIES_GLOBALDEFINITIONS_HPP #include "classfile_constants.h" -#include "utilities/checkedCast.hpp" #include "utilities/compilerWarnings.hpp" #include "utilities/debug.hpp" #include "utilities/forbiddenFunctions.hpp" @@ -1254,21 +1253,13 @@ JAVA_INTEGER_SHIFT_OP(>>, java_shift_right_unsigned, jlong, julong) #undef JAVA_INTEGER_SHIFT_OP -inline jlong java_negate(jlong v, BasicType bt) { - if (bt == T_INT) { - return java_negate(checked_cast(v)); - } - assert(bt == T_LONG, "int or long only"); - return java_negate(v); -} - // Some convenient bit shift operations that accepts a BasicType as the last // argument. These avoid potential mistakes with overloaded functions only // distinguished by lhs argument type. #define JAVA_INTEGER_SHIFT_BASIC_TYPE(FUNC) \ inline jlong FUNC(jlong lhs, jint rhs, BasicType bt) { \ if (bt == T_INT) { \ - return FUNC(checked_cast(lhs), rhs); \ + return FUNC((jint) lhs, rhs); \ } \ assert(bt == T_LONG, "unsupported basic type"); \ return FUNC(lhs, rhs); \ diff --git a/src/hotspot/share/utilities/vmError.cpp b/src/hotspot/share/utilities/vmError.cpp index e0cbb60c74422..0fbd8ed4259ac 100644 --- a/src/hotspot/share/utilities/vmError.cpp +++ b/src/hotspot/share/utilities/vmError.cpp @@ -60,7 +60,6 @@ #include "runtime/vm_version.hpp" #include "runtime/vmOperations.hpp" #include "runtime/vmThread.hpp" -#include "sanitizers/address.hpp" #include "sanitizers/ub.hpp" #include "utilities/debug.hpp" #include "utilities/decoder.hpp" @@ -911,16 +910,7 @@ void VMError::report(outputStream* st, bool _verbose) { STEP_IF("printing date and time", _verbose) os::print_date_and_time(st, buf, sizeof(buf)); -#ifdef ADDRESS_SANITIZER - STEP_IF("printing ASAN error information", _verbose && Asan::had_error()) - st->cr(); - st->print_cr("------------------ A S A N ----------------"); - st->cr(); - Asan::report(st); - st->cr(); -#endif // ADDRESS_SANITIZER - - STEP_IF("printing thread", _verbose) + STEP_IF("printing thread", _verbose) st->cr(); st->print_cr("--------------- T H R E A D ---------------"); st->cr(); @@ -2196,14 +2186,6 @@ void VMError::controlled_crash(int how) { fatal("Force crash with a nested ThreadsListHandle."); } } - case 18: { - // Trigger an error that should cause ASAN to report a double free or use-after-free. - // Please note that this is not 100% bullet-proof since it assumes that this block - // is not immediately repurposed by some other thread after free. - void* const p = os::malloc(4096, mtTest); - os::free(p); - os::free(p); - } default: // If another number is given, give a generic crash. fatal("Crashing with number %d", how); diff --git a/src/java.base/share/classes/com/sun/crypto/provider/AESCipher.java b/src/java.base/share/classes/com/sun/crypto/provider/AESCipher.java index 329f367717a95..12359cba7d12a 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/AESCipher.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/AESCipher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2022, 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 @@ -49,7 +49,7 @@ * * @author Valerie Peng * - * @see AES_Crypt + * @see AESCrypt * @see CipherBlockChaining * @see ElectronicCodeBook * @see CipherFeedback @@ -174,7 +174,7 @@ static void checkKeySize(Key key, int fixedKeySize) * PKCS5Padding. */ protected AESCipher(int keySize) { - core = new CipherCore(new AES_Crypt(), AESConstants.AES_BLOCK_SIZE); + core = new CipherCore(new AESCrypt(), AESConstants.AES_BLOCK_SIZE); fixedKeySize = keySize; } @@ -504,7 +504,7 @@ protected int engineDoFinal(byte[] input, int inputOffset, int inputLen, protected int engineGetKeySize(Key key) throws InvalidKeyException { byte[] encoded = key.getEncoded(); Arrays.fill(encoded, (byte)0); - if (!AES_Crypt.isKeySizeValid(encoded.length)) { + if (!AESCrypt.isKeySizeValid(encoded.length)) { throw new InvalidKeyException("Invalid AES key length: " + encoded.length + " bytes"); } diff --git a/src/java.base/share/classes/com/sun/crypto/provider/AESCrypt.java b/src/java.base/share/classes/com/sun/crypto/provider/AESCrypt.java new file mode 100644 index 0000000000000..9bbc8c1676485 --- /dev/null +++ b/src/java.base/share/classes/com/sun/crypto/provider/AESCrypt.java @@ -0,0 +1,1437 @@ +/* + * Copyright (c) 2002, 2022, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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. + */ + +/* $Id: Rijndael.java,v 1.6 2000/02/10 01:31:41 gelderen Exp $ + * + * Copyright (C) 1995-2000 The Cryptix Foundation Limited. + * All rights reserved. + * + * Use, modification, copying and distribution of this softwareas is subject + * the terms and conditions of the Cryptix General Licence. You should have + * received a copy of the Cryptix General Licence along with this library; + * if not, you can download a copy from http://www.cryptix.org/ . + */ + +package com.sun.crypto.provider; + +import java.security.InvalidKeyException; +import java.security.MessageDigest; +import java.util.Arrays; + +import jdk.internal.vm.annotation.IntrinsicCandidate; + +/** + * Rijndael --pronounced Reindaal-- is a symmetric cipher with a 128-bit + * block size and variable key-size (128-, 192- and 256-bit). + *

+ * Rijndael was designed by Vincent + * Rijmen and Joan Daemen. + */ +final class AESCrypt extends SymmetricCipher implements AESConstants { + // + // Pre-computed tables, which are copied or derived from FIPS 197. + // + + // the pre-computed substitution table (S-box), 256 bytes + private static final byte[] S = { + (byte)0x63, (byte)0x7C, (byte)0x77, (byte)0x7B, + (byte)0xF2, (byte)0x6B, (byte)0x6F, (byte)0xC5, + (byte)0x30, (byte)0x01, (byte)0x67, (byte)0x2B, + (byte)0xFE, (byte)0xD7, (byte)0xAB, (byte)0x76, + (byte)0xCA, (byte)0x82, (byte)0xC9, (byte)0x7D, + (byte)0xFA, (byte)0x59, (byte)0x47, (byte)0xF0, + (byte)0xAD, (byte)0xD4, (byte)0xA2, (byte)0xAF, + (byte)0x9C, (byte)0xA4, (byte)0x72, (byte)0xC0, + (byte)0xB7, (byte)0xFD, (byte)0x93, (byte)0x26, + (byte)0x36, (byte)0x3F, (byte)0xF7, (byte)0xCC, + (byte)0x34, (byte)0xA5, (byte)0xE5, (byte)0xF1, + (byte)0x71, (byte)0xD8, (byte)0x31, (byte)0x15, + (byte)0x04, (byte)0xC7, (byte)0x23, (byte)0xC3, + (byte)0x18, (byte)0x96, (byte)0x05, (byte)0x9A, + (byte)0x07, (byte)0x12, (byte)0x80, (byte)0xE2, + (byte)0xEB, (byte)0x27, (byte)0xB2, (byte)0x75, + (byte)0x09, (byte)0x83, (byte)0x2C, (byte)0x1A, + (byte)0x1B, (byte)0x6E, (byte)0x5A, (byte)0xA0, + (byte)0x52, (byte)0x3B, (byte)0xD6, (byte)0xB3, + (byte)0x29, (byte)0xE3, (byte)0x2F, (byte)0x84, + (byte)0x53, (byte)0xD1, (byte)0x00, (byte)0xED, + (byte)0x20, (byte)0xFC, (byte)0xB1, (byte)0x5B, + (byte)0x6A, (byte)0xCB, (byte)0xBE, (byte)0x39, + (byte)0x4A, (byte)0x4C, (byte)0x58, (byte)0xCF, + (byte)0xD0, (byte)0xEF, (byte)0xAA, (byte)0xFB, + (byte)0x43, (byte)0x4D, (byte)0x33, (byte)0x85, + (byte)0x45, (byte)0xF9, (byte)0x02, (byte)0x7F, + (byte)0x50, (byte)0x3C, (byte)0x9F, (byte)0xA8, + (byte)0x51, (byte)0xA3, (byte)0x40, (byte)0x8F, + (byte)0x92, (byte)0x9D, (byte)0x38, (byte)0xF5, + (byte)0xBC, (byte)0xB6, (byte)0xDA, (byte)0x21, + (byte)0x10, (byte)0xFF, (byte)0xF3, (byte)0xD2, + (byte)0xCD, (byte)0x0C, (byte)0x13, (byte)0xEC, + (byte)0x5F, (byte)0x97, (byte)0x44, (byte)0x17, + (byte)0xC4, (byte)0xA7, (byte)0x7E, (byte)0x3D, + (byte)0x64, (byte)0x5D, (byte)0x19, (byte)0x73, + (byte)0x60, (byte)0x81, (byte)0x4F, (byte)0xDC, + (byte)0x22, (byte)0x2A, (byte)0x90, (byte)0x88, + (byte)0x46, (byte)0xEE, (byte)0xB8, (byte)0x14, + (byte)0xDE, (byte)0x5E, (byte)0x0B, (byte)0xDB, + (byte)0xE0, (byte)0x32, (byte)0x3A, (byte)0x0A, + (byte)0x49, (byte)0x06, (byte)0x24, (byte)0x5C, + (byte)0xC2, (byte)0xD3, (byte)0xAC, (byte)0x62, + (byte)0x91, (byte)0x95, (byte)0xE4, (byte)0x79, + (byte)0xE7, (byte)0xC8, (byte)0x37, (byte)0x6D, + (byte)0x8D, (byte)0xD5, (byte)0x4E, (byte)0xA9, + (byte)0x6C, (byte)0x56, (byte)0xF4, (byte)0xEA, + (byte)0x65, (byte)0x7A, (byte)0xAE, (byte)0x08, + (byte)0xBA, (byte)0x78, (byte)0x25, (byte)0x2E, + (byte)0x1C, (byte)0xA6, (byte)0xB4, (byte)0xC6, + (byte)0xE8, (byte)0xDD, (byte)0x74, (byte)0x1F, + (byte)0x4B, (byte)0xBD, (byte)0x8B, (byte)0x8A, + (byte)0x70, (byte)0x3E, (byte)0xB5, (byte)0x66, + (byte)0x48, (byte)0x03, (byte)0xF6, (byte)0x0E, + (byte)0x61, (byte)0x35, (byte)0x57, (byte)0xB9, + (byte)0x86, (byte)0xC1, (byte)0x1D, (byte)0x9E, + (byte)0xE1, (byte)0xF8, (byte)0x98, (byte)0x11, + (byte)0x69, (byte)0xD9, (byte)0x8E, (byte)0x94, + (byte)0x9B, (byte)0x1E, (byte)0x87, (byte)0xE9, + (byte)0xCE, (byte)0x55, (byte)0x28, (byte)0xDF, + (byte)0x8C, (byte)0xA1, (byte)0x89, (byte)0x0D, + (byte)0xBF, (byte)0xE6, (byte)0x42, (byte)0x68, + (byte)0x41, (byte)0x99, (byte)0x2D, (byte)0x0F, + (byte)0xB0, (byte)0x54, (byte)0xBB, (byte)0x16, + }; + + // the pre-computed substitution table (inverse S-box), 256 bytes + private static final byte[] Si = { + (byte)0x52, (byte)0x09, (byte)0x6A, (byte)0xD5, + (byte)0x30, (byte)0x36, (byte)0xA5, (byte)0x38, + (byte)0xBF, (byte)0x40, (byte)0xA3, (byte)0x9E, + (byte)0x81, (byte)0xF3, (byte)0xD7, (byte)0xFB, + (byte)0x7C, (byte)0xE3, (byte)0x39, (byte)0x82, + (byte)0x9B, (byte)0x2F, (byte)0xFF, (byte)0x87, + (byte)0x34, (byte)0x8E, (byte)0x43, (byte)0x44, + (byte)0xC4, (byte)0xDE, (byte)0xE9, (byte)0xCB, + (byte)0x54, (byte)0x7B, (byte)0x94, (byte)0x32, + (byte)0xA6, (byte)0xC2, (byte)0x23, (byte)0x3D, + (byte)0xEE, (byte)0x4C, (byte)0x95, (byte)0x0B, + (byte)0x42, (byte)0xFA, (byte)0xC3, (byte)0x4E, + (byte)0x08, (byte)0x2E, (byte)0xA1, (byte)0x66, + (byte)0x28, (byte)0xD9, (byte)0x24, (byte)0xB2, + (byte)0x76, (byte)0x5B, (byte)0xA2, (byte)0x49, + (byte)0x6D, (byte)0x8B, (byte)0xD1, (byte)0x25, + (byte)0x72, (byte)0xF8, (byte)0xF6, (byte)0x64, + (byte)0x86, (byte)0x68, (byte)0x98, (byte)0x16, + (byte)0xD4, (byte)0xA4, (byte)0x5C, (byte)0xCC, + (byte)0x5D, (byte)0x65, (byte)0xB6, (byte)0x92, + (byte)0x6C, (byte)0x70, (byte)0x48, (byte)0x50, + (byte)0xFD, (byte)0xED, (byte)0xB9, (byte)0xDA, + (byte)0x5E, (byte)0x15, (byte)0x46, (byte)0x57, + (byte)0xA7, (byte)0x8D, (byte)0x9D, (byte)0x84, + (byte)0x90, (byte)0xD8, (byte)0xAB, (byte)0x00, + (byte)0x8C, (byte)0xBC, (byte)0xD3, (byte)0x0A, + (byte)0xF7, (byte)0xE4, (byte)0x58, (byte)0x05, + (byte)0xB8, (byte)0xB3, (byte)0x45, (byte)0x06, + (byte)0xD0, (byte)0x2C, (byte)0x1E, (byte)0x8F, + (byte)0xCA, (byte)0x3F, (byte)0x0F, (byte)0x02, + (byte)0xC1, (byte)0xAF, (byte)0xBD, (byte)0x03, + (byte)0x01, (byte)0x13, (byte)0x8A, (byte)0x6B, + (byte)0x3A, (byte)0x91, (byte)0x11, (byte)0x41, + (byte)0x4F, (byte)0x67, (byte)0xDC, (byte)0xEA, + (byte)0x97, (byte)0xF2, (byte)0xCF, (byte)0xCE, + (byte)0xF0, (byte)0xB4, (byte)0xE6, (byte)0x73, + (byte)0x96, (byte)0xAC, (byte)0x74, (byte)0x22, + (byte)0xE7, (byte)0xAD, (byte)0x35, (byte)0x85, + (byte)0xE2, (byte)0xF9, (byte)0x37, (byte)0xE8, + (byte)0x1C, (byte)0x75, (byte)0xDF, (byte)0x6E, + (byte)0x47, (byte)0xF1, (byte)0x1A, (byte)0x71, + (byte)0x1D, (byte)0x29, (byte)0xC5, (byte)0x89, + (byte)0x6F, (byte)0xB7, (byte)0x62, (byte)0x0E, + (byte)0xAA, (byte)0x18, (byte)0xBE, (byte)0x1B, + (byte)0xFC, (byte)0x56, (byte)0x3E, (byte)0x4B, + (byte)0xC6, (byte)0xD2, (byte)0x79, (byte)0x20, + (byte)0x9A, (byte)0xDB, (byte)0xC0, (byte)0xFE, + (byte)0x78, (byte)0xCD, (byte)0x5A, (byte)0xF4, + (byte)0x1F, (byte)0xDD, (byte)0xA8, (byte)0x33, + (byte)0x88, (byte)0x07, (byte)0xC7, (byte)0x31, + (byte)0xB1, (byte)0x12, (byte)0x10, (byte)0x59, + (byte)0x27, (byte)0x80, (byte)0xEC, (byte)0x5F, + (byte)0x60, (byte)0x51, (byte)0x7F, (byte)0xA9, + (byte)0x19, (byte)0xB5, (byte)0x4A, (byte)0x0D, + (byte)0x2D, (byte)0xE5, (byte)0x7A, (byte)0x9F, + (byte)0x93, (byte)0xC9, (byte)0x9C, (byte)0xEF, + (byte)0xA0, (byte)0xE0, (byte)0x3B, (byte)0x4D, + (byte)0xAE, (byte)0x2A, (byte)0xF5, (byte)0xB0, + (byte)0xC8, (byte)0xEB, (byte)0xBB, (byte)0x3C, + (byte)0x83, (byte)0x53, (byte)0x99, (byte)0x61, + (byte)0x17, (byte)0x2B, (byte)0x04, (byte)0x7E, + (byte)0xBA, (byte)0x77, (byte)0xD6, (byte)0x26, + (byte)0xE1, (byte)0x69, (byte)0x14, (byte)0x63, + (byte)0x55, (byte)0x21, (byte)0x0C, (byte)0x7D, + }; + + // pre-computed tables (T-box) + private static final int[] T1 = { + 0xC66363A5, 0xF87C7C84, 0xEE777799, 0xF67B7B8D, + 0xFFF2F20D, 0xD66B6BBD, 0xDE6F6FB1, 0x91C5C554, + 0x60303050, 0x02010103, 0xCE6767A9, 0x562B2B7D, + 0xE7FEFE19, 0xB5D7D762, 0x4DABABE6, 0xEC76769A, + 0x8FCACA45, 0x1F82829D, 0x89C9C940, 0xFA7D7D87, + 0xEFFAFA15, 0xB25959EB, 0x8E4747C9, 0xFBF0F00B, + 0x41ADADEC, 0xB3D4D467, 0x5FA2A2FD, 0x45AFAFEA, + 0x239C9CBF, 0x53A4A4F7, 0xE4727296, 0x9BC0C05B, + 0x75B7B7C2, 0xE1FDFD1C, 0x3D9393AE, 0x4C26266A, + 0x6C36365A, 0x7E3F3F41, 0xF5F7F702, 0x83CCCC4F, + 0x6834345C, 0x51A5A5F4, 0xD1E5E534, 0xF9F1F108, + 0xE2717193, 0xABD8D873, 0x62313153, 0x2A15153F, + 0x0804040C, 0x95C7C752, 0x46232365, 0x9DC3C35E, + 0x30181828, 0x379696A1, 0x0A05050F, 0x2F9A9AB5, + 0x0E070709, 0x24121236, 0x1B80809B, 0xDFE2E23D, + 0xCDEBEB26, 0x4E272769, 0x7FB2B2CD, 0xEA75759F, + 0x1209091B, 0x1D83839E, 0x582C2C74, 0x341A1A2E, + 0x361B1B2D, 0xDC6E6EB2, 0xB45A5AEE, 0x5BA0A0FB, + 0xA45252F6, 0x763B3B4D, 0xB7D6D661, 0x7DB3B3CE, + 0x5229297B, 0xDDE3E33E, 0x5E2F2F71, 0x13848497, + 0xA65353F5, 0xB9D1D168, 0x00000000, 0xC1EDED2C, + 0x40202060, 0xE3FCFC1F, 0x79B1B1C8, 0xB65B5BED, + 0xD46A6ABE, 0x8DCBCB46, 0x67BEBED9, 0x7239394B, + 0x944A4ADE, 0x984C4CD4, 0xB05858E8, 0x85CFCF4A, + 0xBBD0D06B, 0xC5EFEF2A, 0x4FAAAAE5, 0xEDFBFB16, + 0x864343C5, 0x9A4D4DD7, 0x66333355, 0x11858594, + 0x8A4545CF, 0xE9F9F910, 0x04020206, 0xFE7F7F81, + 0xA05050F0, 0x783C3C44, 0x259F9FBA, 0x4BA8A8E3, + 0xA25151F3, 0x5DA3A3FE, 0x804040C0, 0x058F8F8A, + 0x3F9292AD, 0x219D9DBC, 0x70383848, 0xF1F5F504, + 0x63BCBCDF, 0x77B6B6C1, 0xAFDADA75, 0x42212163, + 0x20101030, 0xE5FFFF1A, 0xFDF3F30E, 0xBFD2D26D, + 0x81CDCD4C, 0x180C0C14, 0x26131335, 0xC3ECEC2F, + 0xBE5F5FE1, 0x359797A2, 0x884444CC, 0x2E171739, + 0x93C4C457, 0x55A7A7F2, 0xFC7E7E82, 0x7A3D3D47, + 0xC86464AC, 0xBA5D5DE7, 0x3219192B, 0xE6737395, + 0xC06060A0, 0x19818198, 0x9E4F4FD1, 0xA3DCDC7F, + 0x44222266, 0x542A2A7E, 0x3B9090AB, 0x0B888883, + 0x8C4646CA, 0xC7EEEE29, 0x6BB8B8D3, 0x2814143C, + 0xA7DEDE79, 0xBC5E5EE2, 0x160B0B1D, 0xADDBDB76, + 0xDBE0E03B, 0x64323256, 0x743A3A4E, 0x140A0A1E, + 0x924949DB, 0x0C06060A, 0x4824246C, 0xB85C5CE4, + 0x9FC2C25D, 0xBDD3D36E, 0x43ACACEF, 0xC46262A6, + 0x399191A8, 0x319595A4, 0xD3E4E437, 0xF279798B, + 0xD5E7E732, 0x8BC8C843, 0x6E373759, 0xDA6D6DB7, + 0x018D8D8C, 0xB1D5D564, 0x9C4E4ED2, 0x49A9A9E0, + 0xD86C6CB4, 0xAC5656FA, 0xF3F4F407, 0xCFEAEA25, + 0xCA6565AF, 0xF47A7A8E, 0x47AEAEE9, 0x10080818, + 0x6FBABAD5, 0xF0787888, 0x4A25256F, 0x5C2E2E72, + 0x381C1C24, 0x57A6A6F1, 0x73B4B4C7, 0x97C6C651, + 0xCBE8E823, 0xA1DDDD7C, 0xE874749C, 0x3E1F1F21, + 0x964B4BDD, 0x61BDBDDC, 0x0D8B8B86, 0x0F8A8A85, + 0xE0707090, 0x7C3E3E42, 0x71B5B5C4, 0xCC6666AA, + 0x904848D8, 0x06030305, 0xF7F6F601, 0x1C0E0E12, + 0xC26161A3, 0x6A35355F, 0xAE5757F9, 0x69B9B9D0, + 0x17868691, 0x99C1C158, 0x3A1D1D27, 0x279E9EB9, + 0xD9E1E138, 0xEBF8F813, 0x2B9898B3, 0x22111133, + 0xD26969BB, 0xA9D9D970, 0x078E8E89, 0x339494A7, + 0x2D9B9BB6, 0x3C1E1E22, 0x15878792, 0xC9E9E920, + 0x87CECE49, 0xAA5555FF, 0x50282878, 0xA5DFDF7A, + 0x038C8C8F, 0x59A1A1F8, 0x09898980, 0x1A0D0D17, + 0x65BFBFDA, 0xD7E6E631, 0x844242C6, 0xD06868B8, + 0x824141C3, 0x299999B0, 0x5A2D2D77, 0x1E0F0F11, + 0x7BB0B0CB, 0xA85454FC, 0x6DBBBBD6, 0x2C16163A, + }; + + private static final int[] T2 = { + 0xA5C66363, 0x84F87C7C, 0x99EE7777, 0x8DF67B7B, + 0x0DFFF2F2, 0xBDD66B6B, 0xB1DE6F6F, 0x5491C5C5, + 0x50603030, 0x03020101, 0xA9CE6767, 0x7D562B2B, + 0x19E7FEFE, 0x62B5D7D7, 0xE64DABAB, 0x9AEC7676, + 0x458FCACA, 0x9D1F8282, 0x4089C9C9, 0x87FA7D7D, + 0x15EFFAFA, 0xEBB25959, 0xC98E4747, 0x0BFBF0F0, + 0xEC41ADAD, 0x67B3D4D4, 0xFD5FA2A2, 0xEA45AFAF, + 0xBF239C9C, 0xF753A4A4, 0x96E47272, 0x5B9BC0C0, + 0xC275B7B7, 0x1CE1FDFD, 0xAE3D9393, 0x6A4C2626, + 0x5A6C3636, 0x417E3F3F, 0x02F5F7F7, 0x4F83CCCC, + 0x5C683434, 0xF451A5A5, 0x34D1E5E5, 0x08F9F1F1, + 0x93E27171, 0x73ABD8D8, 0x53623131, 0x3F2A1515, + 0x0C080404, 0x5295C7C7, 0x65462323, 0x5E9DC3C3, + 0x28301818, 0xA1379696, 0x0F0A0505, 0xB52F9A9A, + 0x090E0707, 0x36241212, 0x9B1B8080, 0x3DDFE2E2, + 0x26CDEBEB, 0x694E2727, 0xCD7FB2B2, 0x9FEA7575, + 0x1B120909, 0x9E1D8383, 0x74582C2C, 0x2E341A1A, + 0x2D361B1B, 0xB2DC6E6E, 0xEEB45A5A, 0xFB5BA0A0, + 0xF6A45252, 0x4D763B3B, 0x61B7D6D6, 0xCE7DB3B3, + 0x7B522929, 0x3EDDE3E3, 0x715E2F2F, 0x97138484, + 0xF5A65353, 0x68B9D1D1, 0x00000000, 0x2CC1EDED, + 0x60402020, 0x1FE3FCFC, 0xC879B1B1, 0xEDB65B5B, + 0xBED46A6A, 0x468DCBCB, 0xD967BEBE, 0x4B723939, + 0xDE944A4A, 0xD4984C4C, 0xE8B05858, 0x4A85CFCF, + 0x6BBBD0D0, 0x2AC5EFEF, 0xE54FAAAA, 0x16EDFBFB, + 0xC5864343, 0xD79A4D4D, 0x55663333, 0x94118585, + 0xCF8A4545, 0x10E9F9F9, 0x06040202, 0x81FE7F7F, + 0xF0A05050, 0x44783C3C, 0xBA259F9F, 0xE34BA8A8, + 0xF3A25151, 0xFE5DA3A3, 0xC0804040, 0x8A058F8F, + 0xAD3F9292, 0xBC219D9D, 0x48703838, 0x04F1F5F5, + 0xDF63BCBC, 0xC177B6B6, 0x75AFDADA, 0x63422121, + 0x30201010, 0x1AE5FFFF, 0x0EFDF3F3, 0x6DBFD2D2, + 0x4C81CDCD, 0x14180C0C, 0x35261313, 0x2FC3ECEC, + 0xE1BE5F5F, 0xA2359797, 0xCC884444, 0x392E1717, + 0x5793C4C4, 0xF255A7A7, 0x82FC7E7E, 0x477A3D3D, + 0xACC86464, 0xE7BA5D5D, 0x2B321919, 0x95E67373, + 0xA0C06060, 0x98198181, 0xD19E4F4F, 0x7FA3DCDC, + 0x66442222, 0x7E542A2A, 0xAB3B9090, 0x830B8888, + 0xCA8C4646, 0x29C7EEEE, 0xD36BB8B8, 0x3C281414, + 0x79A7DEDE, 0xE2BC5E5E, 0x1D160B0B, 0x76ADDBDB, + 0x3BDBE0E0, 0x56643232, 0x4E743A3A, 0x1E140A0A, + 0xDB924949, 0x0A0C0606, 0x6C482424, 0xE4B85C5C, + 0x5D9FC2C2, 0x6EBDD3D3, 0xEF43ACAC, 0xA6C46262, + 0xA8399191, 0xA4319595, 0x37D3E4E4, 0x8BF27979, + 0x32D5E7E7, 0x438BC8C8, 0x596E3737, 0xB7DA6D6D, + 0x8C018D8D, 0x64B1D5D5, 0xD29C4E4E, 0xE049A9A9, + 0xB4D86C6C, 0xFAAC5656, 0x07F3F4F4, 0x25CFEAEA, + 0xAFCA6565, 0x8EF47A7A, 0xE947AEAE, 0x18100808, + 0xD56FBABA, 0x88F07878, 0x6F4A2525, 0x725C2E2E, + 0x24381C1C, 0xF157A6A6, 0xC773B4B4, 0x5197C6C6, + 0x23CBE8E8, 0x7CA1DDDD, 0x9CE87474, 0x213E1F1F, + 0xDD964B4B, 0xDC61BDBD, 0x860D8B8B, 0x850F8A8A, + 0x90E07070, 0x427C3E3E, 0xC471B5B5, 0xAACC6666, + 0xD8904848, 0x05060303, 0x01F7F6F6, 0x121C0E0E, + 0xA3C26161, 0x5F6A3535, 0xF9AE5757, 0xD069B9B9, + 0x91178686, 0x5899C1C1, 0x273A1D1D, 0xB9279E9E, + 0x38D9E1E1, 0x13EBF8F8, 0xB32B9898, 0x33221111, + 0xBBD26969, 0x70A9D9D9, 0x89078E8E, 0xA7339494, + 0xB62D9B9B, 0x223C1E1E, 0x92158787, 0x20C9E9E9, + 0x4987CECE, 0xFFAA5555, 0x78502828, 0x7AA5DFDF, + 0x8F038C8C, 0xF859A1A1, 0x80098989, 0x171A0D0D, + 0xDA65BFBF, 0x31D7E6E6, 0xC6844242, 0xB8D06868, + 0xC3824141, 0xB0299999, 0x775A2D2D, 0x111E0F0F, + 0xCB7BB0B0, 0xFCA85454, 0xD66DBBBB, 0x3A2C1616, + }; + + private static final int[] T3 = { + 0x63A5C663, 0x7C84F87C, 0x7799EE77, 0x7B8DF67B, + 0xF20DFFF2, 0x6BBDD66B, 0x6FB1DE6F, 0xC55491C5, + 0x30506030, 0x01030201, 0x67A9CE67, 0x2B7D562B, + 0xFE19E7FE, 0xD762B5D7, 0xABE64DAB, 0x769AEC76, + 0xCA458FCA, 0x829D1F82, 0xC94089C9, 0x7D87FA7D, + 0xFA15EFFA, 0x59EBB259, 0x47C98E47, 0xF00BFBF0, + 0xADEC41AD, 0xD467B3D4, 0xA2FD5FA2, 0xAFEA45AF, + 0x9CBF239C, 0xA4F753A4, 0x7296E472, 0xC05B9BC0, + 0xB7C275B7, 0xFD1CE1FD, 0x93AE3D93, 0x266A4C26, + 0x365A6C36, 0x3F417E3F, 0xF702F5F7, 0xCC4F83CC, + 0x345C6834, 0xA5F451A5, 0xE534D1E5, 0xF108F9F1, + 0x7193E271, 0xD873ABD8, 0x31536231, 0x153F2A15, + 0x040C0804, 0xC75295C7, 0x23654623, 0xC35E9DC3, + 0x18283018, 0x96A13796, 0x050F0A05, 0x9AB52F9A, + 0x07090E07, 0x12362412, 0x809B1B80, 0xE23DDFE2, + 0xEB26CDEB, 0x27694E27, 0xB2CD7FB2, 0x759FEA75, + 0x091B1209, 0x839E1D83, 0x2C74582C, 0x1A2E341A, + 0x1B2D361B, 0x6EB2DC6E, 0x5AEEB45A, 0xA0FB5BA0, + 0x52F6A452, 0x3B4D763B, 0xD661B7D6, 0xB3CE7DB3, + 0x297B5229, 0xE33EDDE3, 0x2F715E2F, 0x84971384, + 0x53F5A653, 0xD168B9D1, 0x00000000, 0xED2CC1ED, + 0x20604020, 0xFC1FE3FC, 0xB1C879B1, 0x5BEDB65B, + 0x6ABED46A, 0xCB468DCB, 0xBED967BE, 0x394B7239, + 0x4ADE944A, 0x4CD4984C, 0x58E8B058, 0xCF4A85CF, + 0xD06BBBD0, 0xEF2AC5EF, 0xAAE54FAA, 0xFB16EDFB, + 0x43C58643, 0x4DD79A4D, 0x33556633, 0x85941185, + 0x45CF8A45, 0xF910E9F9, 0x02060402, 0x7F81FE7F, + 0x50F0A050, 0x3C44783C, 0x9FBA259F, 0xA8E34BA8, + 0x51F3A251, 0xA3FE5DA3, 0x40C08040, 0x8F8A058F, + 0x92AD3F92, 0x9DBC219D, 0x38487038, 0xF504F1F5, + 0xBCDF63BC, 0xB6C177B6, 0xDA75AFDA, 0x21634221, + 0x10302010, 0xFF1AE5FF, 0xF30EFDF3, 0xD26DBFD2, + 0xCD4C81CD, 0x0C14180C, 0x13352613, 0xEC2FC3EC, + 0x5FE1BE5F, 0x97A23597, 0x44CC8844, 0x17392E17, + 0xC45793C4, 0xA7F255A7, 0x7E82FC7E, 0x3D477A3D, + 0x64ACC864, 0x5DE7BA5D, 0x192B3219, 0x7395E673, + 0x60A0C060, 0x81981981, 0x4FD19E4F, 0xDC7FA3DC, + 0x22664422, 0x2A7E542A, 0x90AB3B90, 0x88830B88, + 0x46CA8C46, 0xEE29C7EE, 0xB8D36BB8, 0x143C2814, + 0xDE79A7DE, 0x5EE2BC5E, 0x0B1D160B, 0xDB76ADDB, + 0xE03BDBE0, 0x32566432, 0x3A4E743A, 0x0A1E140A, + 0x49DB9249, 0x060A0C06, 0x246C4824, 0x5CE4B85C, + 0xC25D9FC2, 0xD36EBDD3, 0xACEF43AC, 0x62A6C462, + 0x91A83991, 0x95A43195, 0xE437D3E4, 0x798BF279, + 0xE732D5E7, 0xC8438BC8, 0x37596E37, 0x6DB7DA6D, + 0x8D8C018D, 0xD564B1D5, 0x4ED29C4E, 0xA9E049A9, + 0x6CB4D86C, 0x56FAAC56, 0xF407F3F4, 0xEA25CFEA, + 0x65AFCA65, 0x7A8EF47A, 0xAEE947AE, 0x08181008, + 0xBAD56FBA, 0x7888F078, 0x256F4A25, 0x2E725C2E, + 0x1C24381C, 0xA6F157A6, 0xB4C773B4, 0xC65197C6, + 0xE823CBE8, 0xDD7CA1DD, 0x749CE874, 0x1F213E1F, + 0x4BDD964B, 0xBDDC61BD, 0x8B860D8B, 0x8A850F8A, + 0x7090E070, 0x3E427C3E, 0xB5C471B5, 0x66AACC66, + 0x48D89048, 0x03050603, 0xF601F7F6, 0x0E121C0E, + 0x61A3C261, 0x355F6A35, 0x57F9AE57, 0xB9D069B9, + 0x86911786, 0xC15899C1, 0x1D273A1D, 0x9EB9279E, + 0xE138D9E1, 0xF813EBF8, 0x98B32B98, 0x11332211, + 0x69BBD269, 0xD970A9D9, 0x8E89078E, 0x94A73394, + 0x9BB62D9B, 0x1E223C1E, 0x87921587, 0xE920C9E9, + 0xCE4987CE, 0x55FFAA55, 0x28785028, 0xDF7AA5DF, + 0x8C8F038C, 0xA1F859A1, 0x89800989, 0x0D171A0D, + 0xBFDA65BF, 0xE631D7E6, 0x42C68442, 0x68B8D068, + 0x41C38241, 0x99B02999, 0x2D775A2D, 0x0F111E0F, + 0xB0CB7BB0, 0x54FCA854, 0xBBD66DBB, 0x163A2C16, + }; + + private static final int[] T4 = { + 0x6363A5C6, 0x7C7C84F8, 0x777799EE, 0x7B7B8DF6, + 0xF2F20DFF, 0x6B6BBDD6, 0x6F6FB1DE, 0xC5C55491, + 0x30305060, 0x01010302, 0x6767A9CE, 0x2B2B7D56, + 0xFEFE19E7, 0xD7D762B5, 0xABABE64D, 0x76769AEC, + 0xCACA458F, 0x82829D1F, 0xC9C94089, 0x7D7D87FA, + 0xFAFA15EF, 0x5959EBB2, 0x4747C98E, 0xF0F00BFB, + 0xADADEC41, 0xD4D467B3, 0xA2A2FD5F, 0xAFAFEA45, + 0x9C9CBF23, 0xA4A4F753, 0x727296E4, 0xC0C05B9B, + 0xB7B7C275, 0xFDFD1CE1, 0x9393AE3D, 0x26266A4C, + 0x36365A6C, 0x3F3F417E, 0xF7F702F5, 0xCCCC4F83, + 0x34345C68, 0xA5A5F451, 0xE5E534D1, 0xF1F108F9, + 0x717193E2, 0xD8D873AB, 0x31315362, 0x15153F2A, + 0x04040C08, 0xC7C75295, 0x23236546, 0xC3C35E9D, + 0x18182830, 0x9696A137, 0x05050F0A, 0x9A9AB52F, + 0x0707090E, 0x12123624, 0x80809B1B, 0xE2E23DDF, + 0xEBEB26CD, 0x2727694E, 0xB2B2CD7F, 0x75759FEA, + 0x09091B12, 0x83839E1D, 0x2C2C7458, 0x1A1A2E34, + 0x1B1B2D36, 0x6E6EB2DC, 0x5A5AEEB4, 0xA0A0FB5B, + 0x5252F6A4, 0x3B3B4D76, 0xD6D661B7, 0xB3B3CE7D, + 0x29297B52, 0xE3E33EDD, 0x2F2F715E, 0x84849713, + 0x5353F5A6, 0xD1D168B9, 0x00000000, 0xEDED2CC1, + 0x20206040, 0xFCFC1FE3, 0xB1B1C879, 0x5B5BEDB6, + 0x6A6ABED4, 0xCBCB468D, 0xBEBED967, 0x39394B72, + 0x4A4ADE94, 0x4C4CD498, 0x5858E8B0, 0xCFCF4A85, + 0xD0D06BBB, 0xEFEF2AC5, 0xAAAAE54F, 0xFBFB16ED, + 0x4343C586, 0x4D4DD79A, 0x33335566, 0x85859411, + 0x4545CF8A, 0xF9F910E9, 0x02020604, 0x7F7F81FE, + 0x5050F0A0, 0x3C3C4478, 0x9F9FBA25, 0xA8A8E34B, + 0x5151F3A2, 0xA3A3FE5D, 0x4040C080, 0x8F8F8A05, + 0x9292AD3F, 0x9D9DBC21, 0x38384870, 0xF5F504F1, + 0xBCBCDF63, 0xB6B6C177, 0xDADA75AF, 0x21216342, + 0x10103020, 0xFFFF1AE5, 0xF3F30EFD, 0xD2D26DBF, + 0xCDCD4C81, 0x0C0C1418, 0x13133526, 0xECEC2FC3, + 0x5F5FE1BE, 0x9797A235, 0x4444CC88, 0x1717392E, + 0xC4C45793, 0xA7A7F255, 0x7E7E82FC, 0x3D3D477A, + 0x6464ACC8, 0x5D5DE7BA, 0x19192B32, 0x737395E6, + 0x6060A0C0, 0x81819819, 0x4F4FD19E, 0xDCDC7FA3, + 0x22226644, 0x2A2A7E54, 0x9090AB3B, 0x8888830B, + 0x4646CA8C, 0xEEEE29C7, 0xB8B8D36B, 0x14143C28, + 0xDEDE79A7, 0x5E5EE2BC, 0x0B0B1D16, 0xDBDB76AD, + 0xE0E03BDB, 0x32325664, 0x3A3A4E74, 0x0A0A1E14, + 0x4949DB92, 0x06060A0C, 0x24246C48, 0x5C5CE4B8, + 0xC2C25D9F, 0xD3D36EBD, 0xACACEF43, 0x6262A6C4, + 0x9191A839, 0x9595A431, 0xE4E437D3, 0x79798BF2, + 0xE7E732D5, 0xC8C8438B, 0x3737596E, 0x6D6DB7DA, + 0x8D8D8C01, 0xD5D564B1, 0x4E4ED29C, 0xA9A9E049, + 0x6C6CB4D8, 0x5656FAAC, 0xF4F407F3, 0xEAEA25CF, + 0x6565AFCA, 0x7A7A8EF4, 0xAEAEE947, 0x08081810, + 0xBABAD56F, 0x787888F0, 0x25256F4A, 0x2E2E725C, + 0x1C1C2438, 0xA6A6F157, 0xB4B4C773, 0xC6C65197, + 0xE8E823CB, 0xDDDD7CA1, 0x74749CE8, 0x1F1F213E, + 0x4B4BDD96, 0xBDBDDC61, 0x8B8B860D, 0x8A8A850F, + 0x707090E0, 0x3E3E427C, 0xB5B5C471, 0x6666AACC, + 0x4848D890, 0x03030506, 0xF6F601F7, 0x0E0E121C, + 0x6161A3C2, 0x35355F6A, 0x5757F9AE, 0xB9B9D069, + 0x86869117, 0xC1C15899, 0x1D1D273A, 0x9E9EB927, + 0xE1E138D9, 0xF8F813EB, 0x9898B32B, 0x11113322, + 0x6969BBD2, 0xD9D970A9, 0x8E8E8907, 0x9494A733, + 0x9B9BB62D, 0x1E1E223C, 0x87879215, 0xE9E920C9, + 0xCECE4987, 0x5555FFAA, 0x28287850, 0xDFDF7AA5, + 0x8C8C8F03, 0xA1A1F859, 0x89898009, 0x0D0D171A, + 0xBFBFDA65, 0xE6E631D7, 0x4242C684, 0x6868B8D0, + 0x4141C382, 0x9999B029, 0x2D2D775A, 0x0F0F111E, + 0xB0B0CB7B, 0x5454FCA8, 0xBBBBD66D, 0x16163A2C, + }; + + + // pre-computed inverse tables (inverse T-box) + private static final int[] T5 = { + 0x51F4A750, 0x7E416553, 0x1A17A4C3, 0x3A275E96, + 0x3BAB6BCB, 0x1F9D45F1, 0xACFA58AB, 0x4BE30393, + 0x2030FA55, 0xAD766DF6, 0x88CC7691, 0xF5024C25, + 0x4FE5D7FC, 0xC52ACBD7, 0x26354480, 0xB562A38F, + 0xDEB15A49, 0x25BA1B67, 0x45EA0E98, 0x5DFEC0E1, + 0xC32F7502, 0x814CF012, 0x8D4697A3, 0x6BD3F9C6, + 0x038F5FE7, 0x15929C95, 0xBF6D7AEB, 0x955259DA, + 0xD4BE832D, 0x587421D3, 0x49E06929, 0x8EC9C844, + 0x75C2896A, 0xF48E7978, 0x99583E6B, 0x27B971DD, + 0xBEE14FB6, 0xF088AD17, 0xC920AC66, 0x7DCE3AB4, + 0x63DF4A18, 0xE51A3182, 0x97513360, 0x62537F45, + 0xB16477E0, 0xBB6BAE84, 0xFE81A01C, 0xF9082B94, + 0x70486858, 0x8F45FD19, 0x94DE6C87, 0x527BF8B7, + 0xAB73D323, 0x724B02E2, 0xE31F8F57, 0x6655AB2A, + 0xB2EB2807, 0x2FB5C203, 0x86C57B9A, 0xD33708A5, + 0x302887F2, 0x23BFA5B2, 0x02036ABA, 0xED16825C, + 0x8ACF1C2B, 0xA779B492, 0xF307F2F0, 0x4E69E2A1, + 0x65DAF4CD, 0x0605BED5, 0xD134621F, 0xC4A6FE8A, + 0x342E539D, 0xA2F355A0, 0x058AE132, 0xA4F6EB75, + 0x0B83EC39, 0x4060EFAA, 0x5E719F06, 0xBD6E1051, + 0x3E218AF9, 0x96DD063D, 0xDD3E05AE, 0x4DE6BD46, + 0x91548DB5, 0x71C45D05, 0x0406D46F, 0x605015FF, + 0x1998FB24, 0xD6BDE997, 0x894043CC, 0x67D99E77, + 0xB0E842BD, 0x07898B88, 0xE7195B38, 0x79C8EEDB, + 0xA17C0A47, 0x7C420FE9, 0xF8841EC9, 0x00000000, + 0x09808683, 0x322BED48, 0x1E1170AC, 0x6C5A724E, + 0xFD0EFFFB, 0x0F853856, 0x3DAED51E, 0x362D3927, + 0x0A0FD964, 0x685CA621, 0x9B5B54D1, 0x24362E3A, + 0x0C0A67B1, 0x9357E70F, 0xB4EE96D2, 0x1B9B919E, + 0x80C0C54F, 0x61DC20A2, 0x5A774B69, 0x1C121A16, + 0xE293BA0A, 0xC0A02AE5, 0x3C22E043, 0x121B171D, + 0x0E090D0B, 0xF28BC7AD, 0x2DB6A8B9, 0x141EA9C8, + 0x57F11985, 0xAF75074C, 0xEE99DDBB, 0xA37F60FD, + 0xF701269F, 0x5C72F5BC, 0x44663BC5, 0x5BFB7E34, + 0x8B432976, 0xCB23C6DC, 0xB6EDFC68, 0xB8E4F163, + 0xD731DCCA, 0x42638510, 0x13972240, 0x84C61120, + 0x854A247D, 0xD2BB3DF8, 0xAEF93211, 0xC729A16D, + 0x1D9E2F4B, 0xDCB230F3, 0x0D8652EC, 0x77C1E3D0, + 0x2BB3166C, 0xA970B999, 0x119448FA, 0x47E96422, + 0xA8FC8CC4, 0xA0F03F1A, 0x567D2CD8, 0x223390EF, + 0x87494EC7, 0xD938D1C1, 0x8CCAA2FE, 0x98D40B36, + 0xA6F581CF, 0xA57ADE28, 0xDAB78E26, 0x3FADBFA4, + 0x2C3A9DE4, 0x5078920D, 0x6A5FCC9B, 0x547E4662, + 0xF68D13C2, 0x90D8B8E8, 0x2E39F75E, 0x82C3AFF5, + 0x9F5D80BE, 0x69D0937C, 0x6FD52DA9, 0xCF2512B3, + 0xC8AC993B, 0x10187DA7, 0xE89C636E, 0xDB3BBB7B, + 0xCD267809, 0x6E5918F4, 0xEC9AB701, 0x834F9AA8, + 0xE6956E65, 0xAAFFE67E, 0x21BCCF08, 0xEF15E8E6, + 0xBAE79BD9, 0x4A6F36CE, 0xEA9F09D4, 0x29B07CD6, + 0x31A4B2AF, 0x2A3F2331, 0xC6A59430, 0x35A266C0, + 0x744EBC37, 0xFC82CAA6, 0xE090D0B0, 0x33A7D815, + 0xF104984A, 0x41ECDAF7, 0x7FCD500E, 0x1791F62F, + 0x764DD68D, 0x43EFB04D, 0xCCAA4D54, 0xE49604DF, + 0x9ED1B5E3, 0x4C6A881B, 0xC12C1FB8, 0x4665517F, + 0x9D5EEA04, 0x018C355D, 0xFA877473, 0xFB0B412E, + 0xB3671D5A, 0x92DBD252, 0xE9105633, 0x6DD64713, + 0x9AD7618C, 0x37A10C7A, 0x59F8148E, 0xEB133C89, + 0xCEA927EE, 0xB761C935, 0xE11CE5ED, 0x7A47B13C, + 0x9CD2DF59, 0x55F2733F, 0x1814CE79, 0x73C737BF, + 0x53F7CDEA, 0x5FFDAA5B, 0xDF3D6F14, 0x7844DB86, + 0xCAAFF381, 0xB968C43E, 0x3824342C, 0xC2A3405F, + 0x161DC372, 0xBCE2250C, 0x283C498B, 0xFF0D9541, + 0x39A80171, 0x080CB3DE, 0xD8B4E49C, 0x6456C190, + 0x7BCB8461, 0xD532B670, 0x486C5C74, 0xD0B85742, + }; + + private static final int[] T6 = { + 0x5051F4A7, 0x537E4165, 0xC31A17A4, 0x963A275E, + 0xCB3BAB6B, 0xF11F9D45, 0xABACFA58, 0x934BE303, + 0x552030FA, 0xF6AD766D, 0x9188CC76, 0x25F5024C, + 0xFC4FE5D7, 0xD7C52ACB, 0x80263544, 0x8FB562A3, + 0x49DEB15A, 0x6725BA1B, 0x9845EA0E, 0xE15DFEC0, + 0x02C32F75, 0x12814CF0, 0xA38D4697, 0xC66BD3F9, + 0xE7038F5F, 0x9515929C, 0xEBBF6D7A, 0xDA955259, + 0x2DD4BE83, 0xD3587421, 0x2949E069, 0x448EC9C8, + 0x6A75C289, 0x78F48E79, 0x6B99583E, 0xDD27B971, + 0xB6BEE14F, 0x17F088AD, 0x66C920AC, 0xB47DCE3A, + 0x1863DF4A, 0x82E51A31, 0x60975133, 0x4562537F, + 0xE0B16477, 0x84BB6BAE, 0x1CFE81A0, 0x94F9082B, + 0x58704868, 0x198F45FD, 0x8794DE6C, 0xB7527BF8, + 0x23AB73D3, 0xE2724B02, 0x57E31F8F, 0x2A6655AB, + 0x07B2EB28, 0x032FB5C2, 0x9A86C57B, 0xA5D33708, + 0xF2302887, 0xB223BFA5, 0xBA02036A, 0x5CED1682, + 0x2B8ACF1C, 0x92A779B4, 0xF0F307F2, 0xA14E69E2, + 0xCD65DAF4, 0xD50605BE, 0x1FD13462, 0x8AC4A6FE, + 0x9D342E53, 0xA0A2F355, 0x32058AE1, 0x75A4F6EB, + 0x390B83EC, 0xAA4060EF, 0x065E719F, 0x51BD6E10, + 0xF93E218A, 0x3D96DD06, 0xAEDD3E05, 0x464DE6BD, + 0xB591548D, 0x0571C45D, 0x6F0406D4, 0xFF605015, + 0x241998FB, 0x97D6BDE9, 0xCC894043, 0x7767D99E, + 0xBDB0E842, 0x8807898B, 0x38E7195B, 0xDB79C8EE, + 0x47A17C0A, 0xE97C420F, 0xC9F8841E, 0x00000000, + 0x83098086, 0x48322BED, 0xAC1E1170, 0x4E6C5A72, + 0xFBFD0EFF, 0x560F8538, 0x1E3DAED5, 0x27362D39, + 0x640A0FD9, 0x21685CA6, 0xD19B5B54, 0x3A24362E, + 0xB10C0A67, 0x0F9357E7, 0xD2B4EE96, 0x9E1B9B91, + 0x4F80C0C5, 0xA261DC20, 0x695A774B, 0x161C121A, + 0x0AE293BA, 0xE5C0A02A, 0x433C22E0, 0x1D121B17, + 0x0B0E090D, 0xADF28BC7, 0xB92DB6A8, 0xC8141EA9, + 0x8557F119, 0x4CAF7507, 0xBBEE99DD, 0xFDA37F60, + 0x9FF70126, 0xBC5C72F5, 0xC544663B, 0x345BFB7E, + 0x768B4329, 0xDCCB23C6, 0x68B6EDFC, 0x63B8E4F1, + 0xCAD731DC, 0x10426385, 0x40139722, 0x2084C611, + 0x7D854A24, 0xF8D2BB3D, 0x11AEF932, 0x6DC729A1, + 0x4B1D9E2F, 0xF3DCB230, 0xEC0D8652, 0xD077C1E3, + 0x6C2BB316, 0x99A970B9, 0xFA119448, 0x2247E964, + 0xC4A8FC8C, 0x1AA0F03F, 0xD8567D2C, 0xEF223390, + 0xC787494E, 0xC1D938D1, 0xFE8CCAA2, 0x3698D40B, + 0xCFA6F581, 0x28A57ADE, 0x26DAB78E, 0xA43FADBF, + 0xE42C3A9D, 0x0D507892, 0x9B6A5FCC, 0x62547E46, + 0xC2F68D13, 0xE890D8B8, 0x5E2E39F7, 0xF582C3AF, + 0xBE9F5D80, 0x7C69D093, 0xA96FD52D, 0xB3CF2512, + 0x3BC8AC99, 0xA710187D, 0x6EE89C63, 0x7BDB3BBB, + 0x09CD2678, 0xF46E5918, 0x01EC9AB7, 0xA8834F9A, + 0x65E6956E, 0x7EAAFFE6, 0x0821BCCF, 0xE6EF15E8, + 0xD9BAE79B, 0xCE4A6F36, 0xD4EA9F09, 0xD629B07C, + 0xAF31A4B2, 0x312A3F23, 0x30C6A594, 0xC035A266, + 0x37744EBC, 0xA6FC82CA, 0xB0E090D0, 0x1533A7D8, + 0x4AF10498, 0xF741ECDA, 0x0E7FCD50, 0x2F1791F6, + 0x8D764DD6, 0x4D43EFB0, 0x54CCAA4D, 0xDFE49604, + 0xE39ED1B5, 0x1B4C6A88, 0xB8C12C1F, 0x7F466551, + 0x049D5EEA, 0x5D018C35, 0x73FA8774, 0x2EFB0B41, + 0x5AB3671D, 0x5292DBD2, 0x33E91056, 0x136DD647, + 0x8C9AD761, 0x7A37A10C, 0x8E59F814, 0x89EB133C, + 0xEECEA927, 0x35B761C9, 0xEDE11CE5, 0x3C7A47B1, + 0x599CD2DF, 0x3F55F273, 0x791814CE, 0xBF73C737, + 0xEA53F7CD, 0x5B5FFDAA, 0x14DF3D6F, 0x867844DB, + 0x81CAAFF3, 0x3EB968C4, 0x2C382434, 0x5FC2A340, + 0x72161DC3, 0x0CBCE225, 0x8B283C49, 0x41FF0D95, + 0x7139A801, 0xDE080CB3, 0x9CD8B4E4, 0x906456C1, + 0x617BCB84, 0x70D532B6, 0x74486C5C, 0x42D0B857, + }; + + private static final int[] T7 = { + 0xA75051F4, 0x65537E41, 0xA4C31A17, 0x5E963A27, + 0x6BCB3BAB, 0x45F11F9D, 0x58ABACFA, 0x03934BE3, + 0xFA552030, 0x6DF6AD76, 0x769188CC, 0x4C25F502, + 0xD7FC4FE5, 0xCBD7C52A, 0x44802635, 0xA38FB562, + 0x5A49DEB1, 0x1B6725BA, 0x0E9845EA, 0xC0E15DFE, + 0x7502C32F, 0xF012814C, 0x97A38D46, 0xF9C66BD3, + 0x5FE7038F, 0x9C951592, 0x7AEBBF6D, 0x59DA9552, + 0x832DD4BE, 0x21D35874, 0x692949E0, 0xC8448EC9, + 0x896A75C2, 0x7978F48E, 0x3E6B9958, 0x71DD27B9, + 0x4FB6BEE1, 0xAD17F088, 0xAC66C920, 0x3AB47DCE, + 0x4A1863DF, 0x3182E51A, 0x33609751, 0x7F456253, + 0x77E0B164, 0xAE84BB6B, 0xA01CFE81, 0x2B94F908, + 0x68587048, 0xFD198F45, 0x6C8794DE, 0xF8B7527B, + 0xD323AB73, 0x02E2724B, 0x8F57E31F, 0xAB2A6655, + 0x2807B2EB, 0xC2032FB5, 0x7B9A86C5, 0x08A5D337, + 0x87F23028, 0xA5B223BF, 0x6ABA0203, 0x825CED16, + 0x1C2B8ACF, 0xB492A779, 0xF2F0F307, 0xE2A14E69, + 0xF4CD65DA, 0xBED50605, 0x621FD134, 0xFE8AC4A6, + 0x539D342E, 0x55A0A2F3, 0xE132058A, 0xEB75A4F6, + 0xEC390B83, 0xEFAA4060, 0x9F065E71, 0x1051BD6E, + 0x8AF93E21, 0x063D96DD, 0x05AEDD3E, 0xBD464DE6, + 0x8DB59154, 0x5D0571C4, 0xD46F0406, 0x15FF6050, + 0xFB241998, 0xE997D6BD, 0x43CC8940, 0x9E7767D9, + 0x42BDB0E8, 0x8B880789, 0x5B38E719, 0xEEDB79C8, + 0x0A47A17C, 0x0FE97C42, 0x1EC9F884, 0x00000000, + 0x86830980, 0xED48322B, 0x70AC1E11, 0x724E6C5A, + 0xFFFBFD0E, 0x38560F85, 0xD51E3DAE, 0x3927362D, + 0xD9640A0F, 0xA621685C, 0x54D19B5B, 0x2E3A2436, + 0x67B10C0A, 0xE70F9357, 0x96D2B4EE, 0x919E1B9B, + 0xC54F80C0, 0x20A261DC, 0x4B695A77, 0x1A161C12, + 0xBA0AE293, 0x2AE5C0A0, 0xE0433C22, 0x171D121B, + 0x0D0B0E09, 0xC7ADF28B, 0xA8B92DB6, 0xA9C8141E, + 0x198557F1, 0x074CAF75, 0xDDBBEE99, 0x60FDA37F, + 0x269FF701, 0xF5BC5C72, 0x3BC54466, 0x7E345BFB, + 0x29768B43, 0xC6DCCB23, 0xFC68B6ED, 0xF163B8E4, + 0xDCCAD731, 0x85104263, 0x22401397, 0x112084C6, + 0x247D854A, 0x3DF8D2BB, 0x3211AEF9, 0xA16DC729, + 0x2F4B1D9E, 0x30F3DCB2, 0x52EC0D86, 0xE3D077C1, + 0x166C2BB3, 0xB999A970, 0x48FA1194, 0x642247E9, + 0x8CC4A8FC, 0x3F1AA0F0, 0x2CD8567D, 0x90EF2233, + 0x4EC78749, 0xD1C1D938, 0xA2FE8CCA, 0x0B3698D4, + 0x81CFA6F5, 0xDE28A57A, 0x8E26DAB7, 0xBFA43FAD, + 0x9DE42C3A, 0x920D5078, 0xCC9B6A5F, 0x4662547E, + 0x13C2F68D, 0xB8E890D8, 0xF75E2E39, 0xAFF582C3, + 0x80BE9F5D, 0x937C69D0, 0x2DA96FD5, 0x12B3CF25, + 0x993BC8AC, 0x7DA71018, 0x636EE89C, 0xBB7BDB3B, + 0x7809CD26, 0x18F46E59, 0xB701EC9A, 0x9AA8834F, + 0x6E65E695, 0xE67EAAFF, 0xCF0821BC, 0xE8E6EF15, + 0x9BD9BAE7, 0x36CE4A6F, 0x09D4EA9F, 0x7CD629B0, + 0xB2AF31A4, 0x23312A3F, 0x9430C6A5, 0x66C035A2, + 0xBC37744E, 0xCAA6FC82, 0xD0B0E090, 0xD81533A7, + 0x984AF104, 0xDAF741EC, 0x500E7FCD, 0xF62F1791, + 0xD68D764D, 0xB04D43EF, 0x4D54CCAA, 0x04DFE496, + 0xB5E39ED1, 0x881B4C6A, 0x1FB8C12C, 0x517F4665, + 0xEA049D5E, 0x355D018C, 0x7473FA87, 0x412EFB0B, + 0x1D5AB367, 0xD25292DB, 0x5633E910, 0x47136DD6, + 0x618C9AD7, 0x0C7A37A1, 0x148E59F8, 0x3C89EB13, + 0x27EECEA9, 0xC935B761, 0xE5EDE11C, 0xB13C7A47, + 0xDF599CD2, 0x733F55F2, 0xCE791814, 0x37BF73C7, + 0xCDEA53F7, 0xAA5B5FFD, 0x6F14DF3D, 0xDB867844, + 0xF381CAAF, 0xC43EB968, 0x342C3824, 0x405FC2A3, + 0xC372161D, 0x250CBCE2, 0x498B283C, 0x9541FF0D, + 0x017139A8, 0xB3DE080C, 0xE49CD8B4, 0xC1906456, + 0x84617BCB, 0xB670D532, 0x5C74486C, 0x5742D0B8, + }; + + private static final int[] T8 = { + 0xF4A75051, 0x4165537E, 0x17A4C31A, 0x275E963A, + 0xAB6BCB3B, 0x9D45F11F, 0xFA58ABAC, 0xE303934B, + 0x30FA5520, 0x766DF6AD, 0xCC769188, 0x024C25F5, + 0xE5D7FC4F, 0x2ACBD7C5, 0x35448026, 0x62A38FB5, + 0xB15A49DE, 0xBA1B6725, 0xEA0E9845, 0xFEC0E15D, + 0x2F7502C3, 0x4CF01281, 0x4697A38D, 0xD3F9C66B, + 0x8F5FE703, 0x929C9515, 0x6D7AEBBF, 0x5259DA95, + 0xBE832DD4, 0x7421D358, 0xE0692949, 0xC9C8448E, + 0xC2896A75, 0x8E7978F4, 0x583E6B99, 0xB971DD27, + 0xE14FB6BE, 0x88AD17F0, 0x20AC66C9, 0xCE3AB47D, + 0xDF4A1863, 0x1A3182E5, 0x51336097, 0x537F4562, + 0x6477E0B1, 0x6BAE84BB, 0x81A01CFE, 0x082B94F9, + 0x48685870, 0x45FD198F, 0xDE6C8794, 0x7BF8B752, + 0x73D323AB, 0x4B02E272, 0x1F8F57E3, 0x55AB2A66, + 0xEB2807B2, 0xB5C2032F, 0xC57B9A86, 0x3708A5D3, + 0x2887F230, 0xBFA5B223, 0x036ABA02, 0x16825CED, + 0xCF1C2B8A, 0x79B492A7, 0x07F2F0F3, 0x69E2A14E, + 0xDAF4CD65, 0x05BED506, 0x34621FD1, 0xA6FE8AC4, + 0x2E539D34, 0xF355A0A2, 0x8AE13205, 0xF6EB75A4, + 0x83EC390B, 0x60EFAA40, 0x719F065E, 0x6E1051BD, + 0x218AF93E, 0xDD063D96, 0x3E05AEDD, 0xE6BD464D, + 0x548DB591, 0xC45D0571, 0x06D46F04, 0x5015FF60, + 0x98FB2419, 0xBDE997D6, 0x4043CC89, 0xD99E7767, + 0xE842BDB0, 0x898B8807, 0x195B38E7, 0xC8EEDB79, + 0x7C0A47A1, 0x420FE97C, 0x841EC9F8, 0x00000000, + 0x80868309, 0x2BED4832, 0x1170AC1E, 0x5A724E6C, + 0x0EFFFBFD, 0x8538560F, 0xAED51E3D, 0x2D392736, + 0x0FD9640A, 0x5CA62168, 0x5B54D19B, 0x362E3A24, + 0x0A67B10C, 0x57E70F93, 0xEE96D2B4, 0x9B919E1B, + 0xC0C54F80, 0xDC20A261, 0x774B695A, 0x121A161C, + 0x93BA0AE2, 0xA02AE5C0, 0x22E0433C, 0x1B171D12, + 0x090D0B0E, 0x8BC7ADF2, 0xB6A8B92D, 0x1EA9C814, + 0xF1198557, 0x75074CAF, 0x99DDBBEE, 0x7F60FDA3, + 0x01269FF7, 0x72F5BC5C, 0x663BC544, 0xFB7E345B, + 0x4329768B, 0x23C6DCCB, 0xEDFC68B6, 0xE4F163B8, + 0x31DCCAD7, 0x63851042, 0x97224013, 0xC6112084, + 0x4A247D85, 0xBB3DF8D2, 0xF93211AE, 0x29A16DC7, + 0x9E2F4B1D, 0xB230F3DC, 0x8652EC0D, 0xC1E3D077, + 0xB3166C2B, 0x70B999A9, 0x9448FA11, 0xE9642247, + 0xFC8CC4A8, 0xF03F1AA0, 0x7D2CD856, 0x3390EF22, + 0x494EC787, 0x38D1C1D9, 0xCAA2FE8C, 0xD40B3698, + 0xF581CFA6, 0x7ADE28A5, 0xB78E26DA, 0xADBFA43F, + 0x3A9DE42C, 0x78920D50, 0x5FCC9B6A, 0x7E466254, + 0x8D13C2F6, 0xD8B8E890, 0x39F75E2E, 0xC3AFF582, + 0x5D80BE9F, 0xD0937C69, 0xD52DA96F, 0x2512B3CF, + 0xAC993BC8, 0x187DA710, 0x9C636EE8, 0x3BBB7BDB, + 0x267809CD, 0x5918F46E, 0x9AB701EC, 0x4F9AA883, + 0x956E65E6, 0xFFE67EAA, 0xBCCF0821, 0x15E8E6EF, + 0xE79BD9BA, 0x6F36CE4A, 0x9F09D4EA, 0xB07CD629, + 0xA4B2AF31, 0x3F23312A, 0xA59430C6, 0xA266C035, + 0x4EBC3774, 0x82CAA6FC, 0x90D0B0E0, 0xA7D81533, + 0x04984AF1, 0xECDAF741, 0xCD500E7F, 0x91F62F17, + 0x4DD68D76, 0xEFB04D43, 0xAA4D54CC, 0x9604DFE4, + 0xD1B5E39E, 0x6A881B4C, 0x2C1FB8C1, 0x65517F46, + 0x5EEA049D, 0x8C355D01, 0x877473FA, 0x0B412EFB, + 0x671D5AB3, 0xDBD25292, 0x105633E9, 0xD647136D, + 0xD7618C9A, 0xA10C7A37, 0xF8148E59, 0x133C89EB, + 0xA927EECE, 0x61C935B7, 0x1CE5EDE1, 0x47B13C7A, + 0xD2DF599C, 0xF2733F55, 0x14CE7918, 0xC737BF73, + 0xF7CDEA53, 0xFDAA5B5F, 0x3D6F14DF, 0x44DB8678, + 0xAFF381CA, 0x68C43EB9, 0x24342C38, 0xA3405FC2, + 0x1DC37216, 0xE2250CBC, 0x3C498B28, 0x0D9541FF, + 0xA8017139, 0x0CB3DE08, 0xB4E49CD8, 0x56C19064, + 0xCB84617B, 0x32B670D5, 0x6C5C7448, 0xB85742D0, + }; + + private static final int[] U1 = { + 0x00000000, 0x0E090D0B, 0x1C121A16, 0x121B171D, + 0x3824342C, 0x362D3927, 0x24362E3A, 0x2A3F2331, + 0x70486858, 0x7E416553, 0x6C5A724E, 0x62537F45, + 0x486C5C74, 0x4665517F, 0x547E4662, 0x5A774B69, + 0xE090D0B0, 0xEE99DDBB, 0xFC82CAA6, 0xF28BC7AD, + 0xD8B4E49C, 0xD6BDE997, 0xC4A6FE8A, 0xCAAFF381, + 0x90D8B8E8, 0x9ED1B5E3, 0x8CCAA2FE, 0x82C3AFF5, + 0xA8FC8CC4, 0xA6F581CF, 0xB4EE96D2, 0xBAE79BD9, + 0xDB3BBB7B, 0xD532B670, 0xC729A16D, 0xC920AC66, + 0xE31F8F57, 0xED16825C, 0xFF0D9541, 0xF104984A, + 0xAB73D323, 0xA57ADE28, 0xB761C935, 0xB968C43E, + 0x9357E70F, 0x9D5EEA04, 0x8F45FD19, 0x814CF012, + 0x3BAB6BCB, 0x35A266C0, 0x27B971DD, 0x29B07CD6, + 0x038F5FE7, 0x0D8652EC, 0x1F9D45F1, 0x119448FA, + 0x4BE30393, 0x45EA0E98, 0x57F11985, 0x59F8148E, + 0x73C737BF, 0x7DCE3AB4, 0x6FD52DA9, 0x61DC20A2, + 0xAD766DF6, 0xA37F60FD, 0xB16477E0, 0xBF6D7AEB, + 0x955259DA, 0x9B5B54D1, 0x894043CC, 0x87494EC7, + 0xDD3E05AE, 0xD33708A5, 0xC12C1FB8, 0xCF2512B3, + 0xE51A3182, 0xEB133C89, 0xF9082B94, 0xF701269F, + 0x4DE6BD46, 0x43EFB04D, 0x51F4A750, 0x5FFDAA5B, + 0x75C2896A, 0x7BCB8461, 0x69D0937C, 0x67D99E77, + 0x3DAED51E, 0x33A7D815, 0x21BCCF08, 0x2FB5C203, + 0x058AE132, 0x0B83EC39, 0x1998FB24, 0x1791F62F, + 0x764DD68D, 0x7844DB86, 0x6A5FCC9B, 0x6456C190, + 0x4E69E2A1, 0x4060EFAA, 0x527BF8B7, 0x5C72F5BC, + 0x0605BED5, 0x080CB3DE, 0x1A17A4C3, 0x141EA9C8, + 0x3E218AF9, 0x302887F2, 0x223390EF, 0x2C3A9DE4, + 0x96DD063D, 0x98D40B36, 0x8ACF1C2B, 0x84C61120, + 0xAEF93211, 0xA0F03F1A, 0xB2EB2807, 0xBCE2250C, + 0xE6956E65, 0xE89C636E, 0xFA877473, 0xF48E7978, + 0xDEB15A49, 0xD0B85742, 0xC2A3405F, 0xCCAA4D54, + 0x41ECDAF7, 0x4FE5D7FC, 0x5DFEC0E1, 0x53F7CDEA, + 0x79C8EEDB, 0x77C1E3D0, 0x65DAF4CD, 0x6BD3F9C6, + 0x31A4B2AF, 0x3FADBFA4, 0x2DB6A8B9, 0x23BFA5B2, + 0x09808683, 0x07898B88, 0x15929C95, 0x1B9B919E, + 0xA17C0A47, 0xAF75074C, 0xBD6E1051, 0xB3671D5A, + 0x99583E6B, 0x97513360, 0x854A247D, 0x8B432976, + 0xD134621F, 0xDF3D6F14, 0xCD267809, 0xC32F7502, + 0xE9105633, 0xE7195B38, 0xF5024C25, 0xFB0B412E, + 0x9AD7618C, 0x94DE6C87, 0x86C57B9A, 0x88CC7691, + 0xA2F355A0, 0xACFA58AB, 0xBEE14FB6, 0xB0E842BD, + 0xEA9F09D4, 0xE49604DF, 0xF68D13C2, 0xF8841EC9, + 0xD2BB3DF8, 0xDCB230F3, 0xCEA927EE, 0xC0A02AE5, + 0x7A47B13C, 0x744EBC37, 0x6655AB2A, 0x685CA621, + 0x42638510, 0x4C6A881B, 0x5E719F06, 0x5078920D, + 0x0A0FD964, 0x0406D46F, 0x161DC372, 0x1814CE79, + 0x322BED48, 0x3C22E043, 0x2E39F75E, 0x2030FA55, + 0xEC9AB701, 0xE293BA0A, 0xF088AD17, 0xFE81A01C, + 0xD4BE832D, 0xDAB78E26, 0xC8AC993B, 0xC6A59430, + 0x9CD2DF59, 0x92DBD252, 0x80C0C54F, 0x8EC9C844, + 0xA4F6EB75, 0xAAFFE67E, 0xB8E4F163, 0xB6EDFC68, + 0x0C0A67B1, 0x02036ABA, 0x10187DA7, 0x1E1170AC, + 0x342E539D, 0x3A275E96, 0x283C498B, 0x26354480, + 0x7C420FE9, 0x724B02E2, 0x605015FF, 0x6E5918F4, + 0x44663BC5, 0x4A6F36CE, 0x587421D3, 0x567D2CD8, + 0x37A10C7A, 0x39A80171, 0x2BB3166C, 0x25BA1B67, + 0x0F853856, 0x018C355D, 0x13972240, 0x1D9E2F4B, + 0x47E96422, 0x49E06929, 0x5BFB7E34, 0x55F2733F, + 0x7FCD500E, 0x71C45D05, 0x63DF4A18, 0x6DD64713, + 0xD731DCCA, 0xD938D1C1, 0xCB23C6DC, 0xC52ACBD7, + 0xEF15E8E6, 0xE11CE5ED, 0xF307F2F0, 0xFD0EFFFB, + 0xA779B492, 0xA970B999, 0xBB6BAE84, 0xB562A38F, + 0x9F5D80BE, 0x91548DB5, 0x834F9AA8, 0x8D4697A3, + }; + + private static final int[] U2 = { + 0x00000000, 0x0B0E090D, 0x161C121A, 0x1D121B17, + 0x2C382434, 0x27362D39, 0x3A24362E, 0x312A3F23, + 0x58704868, 0x537E4165, 0x4E6C5A72, 0x4562537F, + 0x74486C5C, 0x7F466551, 0x62547E46, 0x695A774B, + 0xB0E090D0, 0xBBEE99DD, 0xA6FC82CA, 0xADF28BC7, + 0x9CD8B4E4, 0x97D6BDE9, 0x8AC4A6FE, 0x81CAAFF3, + 0xE890D8B8, 0xE39ED1B5, 0xFE8CCAA2, 0xF582C3AF, + 0xC4A8FC8C, 0xCFA6F581, 0xD2B4EE96, 0xD9BAE79B, + 0x7BDB3BBB, 0x70D532B6, 0x6DC729A1, 0x66C920AC, + 0x57E31F8F, 0x5CED1682, 0x41FF0D95, 0x4AF10498, + 0x23AB73D3, 0x28A57ADE, 0x35B761C9, 0x3EB968C4, + 0x0F9357E7, 0x049D5EEA, 0x198F45FD, 0x12814CF0, + 0xCB3BAB6B, 0xC035A266, 0xDD27B971, 0xD629B07C, + 0xE7038F5F, 0xEC0D8652, 0xF11F9D45, 0xFA119448, + 0x934BE303, 0x9845EA0E, 0x8557F119, 0x8E59F814, + 0xBF73C737, 0xB47DCE3A, 0xA96FD52D, 0xA261DC20, + 0xF6AD766D, 0xFDA37F60, 0xE0B16477, 0xEBBF6D7A, + 0xDA955259, 0xD19B5B54, 0xCC894043, 0xC787494E, + 0xAEDD3E05, 0xA5D33708, 0xB8C12C1F, 0xB3CF2512, + 0x82E51A31, 0x89EB133C, 0x94F9082B, 0x9FF70126, + 0x464DE6BD, 0x4D43EFB0, 0x5051F4A7, 0x5B5FFDAA, + 0x6A75C289, 0x617BCB84, 0x7C69D093, 0x7767D99E, + 0x1E3DAED5, 0x1533A7D8, 0x0821BCCF, 0x032FB5C2, + 0x32058AE1, 0x390B83EC, 0x241998FB, 0x2F1791F6, + 0x8D764DD6, 0x867844DB, 0x9B6A5FCC, 0x906456C1, + 0xA14E69E2, 0xAA4060EF, 0xB7527BF8, 0xBC5C72F5, + 0xD50605BE, 0xDE080CB3, 0xC31A17A4, 0xC8141EA9, + 0xF93E218A, 0xF2302887, 0xEF223390, 0xE42C3A9D, + 0x3D96DD06, 0x3698D40B, 0x2B8ACF1C, 0x2084C611, + 0x11AEF932, 0x1AA0F03F, 0x07B2EB28, 0x0CBCE225, + 0x65E6956E, 0x6EE89C63, 0x73FA8774, 0x78F48E79, + 0x49DEB15A, 0x42D0B857, 0x5FC2A340, 0x54CCAA4D, + 0xF741ECDA, 0xFC4FE5D7, 0xE15DFEC0, 0xEA53F7CD, + 0xDB79C8EE, 0xD077C1E3, 0xCD65DAF4, 0xC66BD3F9, + 0xAF31A4B2, 0xA43FADBF, 0xB92DB6A8, 0xB223BFA5, + 0x83098086, 0x8807898B, 0x9515929C, 0x9E1B9B91, + 0x47A17C0A, 0x4CAF7507, 0x51BD6E10, 0x5AB3671D, + 0x6B99583E, 0x60975133, 0x7D854A24, 0x768B4329, + 0x1FD13462, 0x14DF3D6F, 0x09CD2678, 0x02C32F75, + 0x33E91056, 0x38E7195B, 0x25F5024C, 0x2EFB0B41, + 0x8C9AD761, 0x8794DE6C, 0x9A86C57B, 0x9188CC76, + 0xA0A2F355, 0xABACFA58, 0xB6BEE14F, 0xBDB0E842, + 0xD4EA9F09, 0xDFE49604, 0xC2F68D13, 0xC9F8841E, + 0xF8D2BB3D, 0xF3DCB230, 0xEECEA927, 0xE5C0A02A, + 0x3C7A47B1, 0x37744EBC, 0x2A6655AB, 0x21685CA6, + 0x10426385, 0x1B4C6A88, 0x065E719F, 0x0D507892, + 0x640A0FD9, 0x6F0406D4, 0x72161DC3, 0x791814CE, + 0x48322BED, 0x433C22E0, 0x5E2E39F7, 0x552030FA, + 0x01EC9AB7, 0x0AE293BA, 0x17F088AD, 0x1CFE81A0, + 0x2DD4BE83, 0x26DAB78E, 0x3BC8AC99, 0x30C6A594, + 0x599CD2DF, 0x5292DBD2, 0x4F80C0C5, 0x448EC9C8, + 0x75A4F6EB, 0x7EAAFFE6, 0x63B8E4F1, 0x68B6EDFC, + 0xB10C0A67, 0xBA02036A, 0xA710187D, 0xAC1E1170, + 0x9D342E53, 0x963A275E, 0x8B283C49, 0x80263544, + 0xE97C420F, 0xE2724B02, 0xFF605015, 0xF46E5918, + 0xC544663B, 0xCE4A6F36, 0xD3587421, 0xD8567D2C, + 0x7A37A10C, 0x7139A801, 0x6C2BB316, 0x6725BA1B, + 0x560F8538, 0x5D018C35, 0x40139722, 0x4B1D9E2F, + 0x2247E964, 0x2949E069, 0x345BFB7E, 0x3F55F273, + 0x0E7FCD50, 0x0571C45D, 0x1863DF4A, 0x136DD647, + 0xCAD731DC, 0xC1D938D1, 0xDCCB23C6, 0xD7C52ACB, + 0xE6EF15E8, 0xEDE11CE5, 0xF0F307F2, 0xFBFD0EFF, + 0x92A779B4, 0x99A970B9, 0x84BB6BAE, 0x8FB562A3, + 0xBE9F5D80, 0xB591548D, 0xA8834F9A, 0xA38D4697, + }; + + private static final int[] U3 = { + 0x00000000, 0x0D0B0E09, 0x1A161C12, 0x171D121B, + 0x342C3824, 0x3927362D, 0x2E3A2436, 0x23312A3F, + 0x68587048, 0x65537E41, 0x724E6C5A, 0x7F456253, + 0x5C74486C, 0x517F4665, 0x4662547E, 0x4B695A77, + 0xD0B0E090, 0xDDBBEE99, 0xCAA6FC82, 0xC7ADF28B, + 0xE49CD8B4, 0xE997D6BD, 0xFE8AC4A6, 0xF381CAAF, + 0xB8E890D8, 0xB5E39ED1, 0xA2FE8CCA, 0xAFF582C3, + 0x8CC4A8FC, 0x81CFA6F5, 0x96D2B4EE, 0x9BD9BAE7, + 0xBB7BDB3B, 0xB670D532, 0xA16DC729, 0xAC66C920, + 0x8F57E31F, 0x825CED16, 0x9541FF0D, 0x984AF104, + 0xD323AB73, 0xDE28A57A, 0xC935B761, 0xC43EB968, + 0xE70F9357, 0xEA049D5E, 0xFD198F45, 0xF012814C, + 0x6BCB3BAB, 0x66C035A2, 0x71DD27B9, 0x7CD629B0, + 0x5FE7038F, 0x52EC0D86, 0x45F11F9D, 0x48FA1194, + 0x03934BE3, 0x0E9845EA, 0x198557F1, 0x148E59F8, + 0x37BF73C7, 0x3AB47DCE, 0x2DA96FD5, 0x20A261DC, + 0x6DF6AD76, 0x60FDA37F, 0x77E0B164, 0x7AEBBF6D, + 0x59DA9552, 0x54D19B5B, 0x43CC8940, 0x4EC78749, + 0x05AEDD3E, 0x08A5D337, 0x1FB8C12C, 0x12B3CF25, + 0x3182E51A, 0x3C89EB13, 0x2B94F908, 0x269FF701, + 0xBD464DE6, 0xB04D43EF, 0xA75051F4, 0xAA5B5FFD, + 0x896A75C2, 0x84617BCB, 0x937C69D0, 0x9E7767D9, + 0xD51E3DAE, 0xD81533A7, 0xCF0821BC, 0xC2032FB5, + 0xE132058A, 0xEC390B83, 0xFB241998, 0xF62F1791, + 0xD68D764D, 0xDB867844, 0xCC9B6A5F, 0xC1906456, + 0xE2A14E69, 0xEFAA4060, 0xF8B7527B, 0xF5BC5C72, + 0xBED50605, 0xB3DE080C, 0xA4C31A17, 0xA9C8141E, + 0x8AF93E21, 0x87F23028, 0x90EF2233, 0x9DE42C3A, + 0x063D96DD, 0x0B3698D4, 0x1C2B8ACF, 0x112084C6, + 0x3211AEF9, 0x3F1AA0F0, 0x2807B2EB, 0x250CBCE2, + 0x6E65E695, 0x636EE89C, 0x7473FA87, 0x7978F48E, + 0x5A49DEB1, 0x5742D0B8, 0x405FC2A3, 0x4D54CCAA, + 0xDAF741EC, 0xD7FC4FE5, 0xC0E15DFE, 0xCDEA53F7, + 0xEEDB79C8, 0xE3D077C1, 0xF4CD65DA, 0xF9C66BD3, + 0xB2AF31A4, 0xBFA43FAD, 0xA8B92DB6, 0xA5B223BF, + 0x86830980, 0x8B880789, 0x9C951592, 0x919E1B9B, + 0x0A47A17C, 0x074CAF75, 0x1051BD6E, 0x1D5AB367, + 0x3E6B9958, 0x33609751, 0x247D854A, 0x29768B43, + 0x621FD134, 0x6F14DF3D, 0x7809CD26, 0x7502C32F, + 0x5633E910, 0x5B38E719, 0x4C25F502, 0x412EFB0B, + 0x618C9AD7, 0x6C8794DE, 0x7B9A86C5, 0x769188CC, + 0x55A0A2F3, 0x58ABACFA, 0x4FB6BEE1, 0x42BDB0E8, + 0x09D4EA9F, 0x04DFE496, 0x13C2F68D, 0x1EC9F884, + 0x3DF8D2BB, 0x30F3DCB2, 0x27EECEA9, 0x2AE5C0A0, + 0xB13C7A47, 0xBC37744E, 0xAB2A6655, 0xA621685C, + 0x85104263, 0x881B4C6A, 0x9F065E71, 0x920D5078, + 0xD9640A0F, 0xD46F0406, 0xC372161D, 0xCE791814, + 0xED48322B, 0xE0433C22, 0xF75E2E39, 0xFA552030, + 0xB701EC9A, 0xBA0AE293, 0xAD17F088, 0xA01CFE81, + 0x832DD4BE, 0x8E26DAB7, 0x993BC8AC, 0x9430C6A5, + 0xDF599CD2, 0xD25292DB, 0xC54F80C0, 0xC8448EC9, + 0xEB75A4F6, 0xE67EAAFF, 0xF163B8E4, 0xFC68B6ED, + 0x67B10C0A, 0x6ABA0203, 0x7DA71018, 0x70AC1E11, + 0x539D342E, 0x5E963A27, 0x498B283C, 0x44802635, + 0x0FE97C42, 0x02E2724B, 0x15FF6050, 0x18F46E59, + 0x3BC54466, 0x36CE4A6F, 0x21D35874, 0x2CD8567D, + 0x0C7A37A1, 0x017139A8, 0x166C2BB3, 0x1B6725BA, + 0x38560F85, 0x355D018C, 0x22401397, 0x2F4B1D9E, + 0x642247E9, 0x692949E0, 0x7E345BFB, 0x733F55F2, + 0x500E7FCD, 0x5D0571C4, 0x4A1863DF, 0x47136DD6, + 0xDCCAD731, 0xD1C1D938, 0xC6DCCB23, 0xCBD7C52A, + 0xE8E6EF15, 0xE5EDE11C, 0xF2F0F307, 0xFFFBFD0E, + 0xB492A779, 0xB999A970, 0xAE84BB6B, 0xA38FB562, + 0x80BE9F5D, 0x8DB59154, 0x9AA8834F, 0x97A38D46, + }; + + private static final int[] U4 = { + 0x00000000, 0x090D0B0E, 0x121A161C, 0x1B171D12, + 0x24342C38, 0x2D392736, 0x362E3A24, 0x3F23312A, + 0x48685870, 0x4165537E, 0x5A724E6C, 0x537F4562, + 0x6C5C7448, 0x65517F46, 0x7E466254, 0x774B695A, + 0x90D0B0E0, 0x99DDBBEE, 0x82CAA6FC, 0x8BC7ADF2, + 0xB4E49CD8, 0xBDE997D6, 0xA6FE8AC4, 0xAFF381CA, + 0xD8B8E890, 0xD1B5E39E, 0xCAA2FE8C, 0xC3AFF582, + 0xFC8CC4A8, 0xF581CFA6, 0xEE96D2B4, 0xE79BD9BA, + 0x3BBB7BDB, 0x32B670D5, 0x29A16DC7, 0x20AC66C9, + 0x1F8F57E3, 0x16825CED, 0x0D9541FF, 0x04984AF1, + 0x73D323AB, 0x7ADE28A5, 0x61C935B7, 0x68C43EB9, + 0x57E70F93, 0x5EEA049D, 0x45FD198F, 0x4CF01281, + 0xAB6BCB3B, 0xA266C035, 0xB971DD27, 0xB07CD629, + 0x8F5FE703, 0x8652EC0D, 0x9D45F11F, 0x9448FA11, + 0xE303934B, 0xEA0E9845, 0xF1198557, 0xF8148E59, + 0xC737BF73, 0xCE3AB47D, 0xD52DA96F, 0xDC20A261, + 0x766DF6AD, 0x7F60FDA3, 0x6477E0B1, 0x6D7AEBBF, + 0x5259DA95, 0x5B54D19B, 0x4043CC89, 0x494EC787, + 0x3E05AEDD, 0x3708A5D3, 0x2C1FB8C1, 0x2512B3CF, + 0x1A3182E5, 0x133C89EB, 0x082B94F9, 0x01269FF7, + 0xE6BD464D, 0xEFB04D43, 0xF4A75051, 0xFDAA5B5F, + 0xC2896A75, 0xCB84617B, 0xD0937C69, 0xD99E7767, + 0xAED51E3D, 0xA7D81533, 0xBCCF0821, 0xB5C2032F, + 0x8AE13205, 0x83EC390B, 0x98FB2419, 0x91F62F17, + 0x4DD68D76, 0x44DB8678, 0x5FCC9B6A, 0x56C19064, + 0x69E2A14E, 0x60EFAA40, 0x7BF8B752, 0x72F5BC5C, + 0x05BED506, 0x0CB3DE08, 0x17A4C31A, 0x1EA9C814, + 0x218AF93E, 0x2887F230, 0x3390EF22, 0x3A9DE42C, + 0xDD063D96, 0xD40B3698, 0xCF1C2B8A, 0xC6112084, + 0xF93211AE, 0xF03F1AA0, 0xEB2807B2, 0xE2250CBC, + 0x956E65E6, 0x9C636EE8, 0x877473FA, 0x8E7978F4, + 0xB15A49DE, 0xB85742D0, 0xA3405FC2, 0xAA4D54CC, + 0xECDAF741, 0xE5D7FC4F, 0xFEC0E15D, 0xF7CDEA53, + 0xC8EEDB79, 0xC1E3D077, 0xDAF4CD65, 0xD3F9C66B, + 0xA4B2AF31, 0xADBFA43F, 0xB6A8B92D, 0xBFA5B223, + 0x80868309, 0x898B8807, 0x929C9515, 0x9B919E1B, + 0x7C0A47A1, 0x75074CAF, 0x6E1051BD, 0x671D5AB3, + 0x583E6B99, 0x51336097, 0x4A247D85, 0x4329768B, + 0x34621FD1, 0x3D6F14DF, 0x267809CD, 0x2F7502C3, + 0x105633E9, 0x195B38E7, 0x024C25F5, 0x0B412EFB, + 0xD7618C9A, 0xDE6C8794, 0xC57B9A86, 0xCC769188, + 0xF355A0A2, 0xFA58ABAC, 0xE14FB6BE, 0xE842BDB0, + 0x9F09D4EA, 0x9604DFE4, 0x8D13C2F6, 0x841EC9F8, + 0xBB3DF8D2, 0xB230F3DC, 0xA927EECE, 0xA02AE5C0, + 0x47B13C7A, 0x4EBC3774, 0x55AB2A66, 0x5CA62168, + 0x63851042, 0x6A881B4C, 0x719F065E, 0x78920D50, + 0x0FD9640A, 0x06D46F04, 0x1DC37216, 0x14CE7918, + 0x2BED4832, 0x22E0433C, 0x39F75E2E, 0x30FA5520, + 0x9AB701EC, 0x93BA0AE2, 0x88AD17F0, 0x81A01CFE, + 0xBE832DD4, 0xB78E26DA, 0xAC993BC8, 0xA59430C6, + 0xD2DF599C, 0xDBD25292, 0xC0C54F80, 0xC9C8448E, + 0xF6EB75A4, 0xFFE67EAA, 0xE4F163B8, 0xEDFC68B6, + 0x0A67B10C, 0x036ABA02, 0x187DA710, 0x1170AC1E, + 0x2E539D34, 0x275E963A, 0x3C498B28, 0x35448026, + 0x420FE97C, 0x4B02E272, 0x5015FF60, 0x5918F46E, + 0x663BC544, 0x6F36CE4A, 0x7421D358, 0x7D2CD856, + 0xA10C7A37, 0xA8017139, 0xB3166C2B, 0xBA1B6725, + 0x8538560F, 0x8C355D01, 0x97224013, 0x9E2F4B1D, + 0xE9642247, 0xE0692949, 0xFB7E345B, 0xF2733F55, + 0xCD500E7F, 0xC45D0571, 0xDF4A1863, 0xD647136D, + 0x31DCCAD7, 0x38D1C1D9, 0x23C6DCCB, 0x2ACBD7C5, + 0x15E8E6EF, 0x1CE5EDE1, 0x07F2F0F3, 0x0EFFFBFD, + 0x79B492A7, 0x70B999A9, 0x6BAE84BB, 0x62A38FB5, + 0x5D80BE9F, 0x548DB591, 0x4F9AA883, 0x4697A38D, + }; + + private static final int[] rcon = { + 0x00000001, 0x00000002, 0x00000004, 0x00000008, + 0x00000010, 0x00000020, 0x00000040, 0x00000080, + 0x0000001B, 0x00000036, 0x0000006C, 0x000000D8, + 0x000000AB, 0x0000004D, 0x0000009A, 0x0000002F, + 0x0000005E, 0x000000BC, 0x00000063, 0x000000C6, + 0x00000097, 0x00000035, 0x0000006A, 0x000000D4, + 0x000000B3, 0x0000007D, 0x000000FA, 0x000000EF, + 0x000000C5, 0x00000091, + }; + + private boolean ROUNDS_12 = false; + private boolean ROUNDS_14 = false; + + /** Session and Sub keys */ + private int[][] sessionK = null; + private int[] K = null; + + /** Cipher encryption/decryption key */ + // skip re-generating Session and Sub keys if the cipher key is + // the same + private byte[] lastKey = null; + + /** ROUNDS * 4 */ + private int limit = 0; + + AESCrypt() { + // empty + } + + /** + * Returns this cipher's block size. + * + * @return this cipher's block size + */ + int getBlockSize() { + return AES_BLOCK_SIZE; + } + + void init(boolean decrypting, String algorithm, byte[] key) + throws InvalidKeyException { + if (!algorithm.equalsIgnoreCase("AES") + && !algorithm.equalsIgnoreCase("Rijndael")) { + throw new InvalidKeyException + ("Wrong algorithm: AES or Rijndael required"); + } + + if (key == null) { // Unlikely, but just double check it. + throw new InvalidKeyException("Empty key"); + } + + if (!MessageDigest.isEqual(key, lastKey)) { + // re-generate session key 'sessionK' when cipher key changes + makeSessionKey(key); + if (lastKey != null) { + Arrays.fill(lastKey, (byte)0); + } + lastKey = key.clone(); // save cipher key + } + + // set sub key to the corresponding session Key + this.K = sessionK[(decrypting? 1:0)]; + } + + // check if the specified length (in bytes) is a valid keysize for AES + static boolean isKeySizeValid(int len) { + for (int aesKeysize : AES_KEYSIZES) { + if (len == aesKeysize) { + return true; + } + } + return false; + } + + /** + * Encrypt exactly one block of plaintext. + */ + void encryptBlock(byte[] in, int inOffset, + byte[] out, int outOffset) { + // Array bound checks are done in caller code, i.e. + // FeedbackCipher.encrypt/decrypt(...) to improve performance. + implEncryptBlock(in, inOffset, out, outOffset); + } + + // Encryption operation. Possibly replaced with a compiler intrinsic. + @IntrinsicCandidate + private void implEncryptBlock(byte[] in, int inOffset, + byte[] out, int outOffset) + { + int keyOffset = 0; + int t0 = ((in[inOffset++] ) << 24 | + (in[inOffset++] & 0xFF) << 16 | + (in[inOffset++] & 0xFF) << 8 | + (in[inOffset++] & 0xFF) ) ^ K[keyOffset++]; + int t1 = ((in[inOffset++] ) << 24 | + (in[inOffset++] & 0xFF) << 16 | + (in[inOffset++] & 0xFF) << 8 | + (in[inOffset++] & 0xFF) ) ^ K[keyOffset++]; + int t2 = ((in[inOffset++] ) << 24 | + (in[inOffset++] & 0xFF) << 16 | + (in[inOffset++] & 0xFF) << 8 | + (in[inOffset++] & 0xFF) ) ^ K[keyOffset++]; + int t3 = ((in[inOffset++] ) << 24 | + (in[inOffset++] & 0xFF) << 16 | + (in[inOffset++] & 0xFF) << 8 | + (in[inOffset] & 0xFF) ) ^ K[keyOffset++]; + + // apply round transforms + while( keyOffset < limit ) + { + int a0, a1, a2; + a0 = T1[(t0 >>> 24) ] ^ + T2[(t1 >>> 16) & 0xFF] ^ + T3[(t2 >>> 8) & 0xFF] ^ + T4[(t3 ) & 0xFF] ^ K[keyOffset++]; + a1 = T1[(t1 >>> 24) ] ^ + T2[(t2 >>> 16) & 0xFF] ^ + T3[(t3 >>> 8) & 0xFF] ^ + T4[(t0 ) & 0xFF] ^ K[keyOffset++]; + a2 = T1[(t2 >>> 24) ] ^ + T2[(t3 >>> 16) & 0xFF] ^ + T3[(t0 >>> 8) & 0xFF] ^ + T4[(t1 ) & 0xFF] ^ K[keyOffset++]; + t3 = T1[(t3 >>> 24) ] ^ + T2[(t0 >>> 16) & 0xFF] ^ + T3[(t1 >>> 8) & 0xFF] ^ + T4[(t2 ) & 0xFF] ^ K[keyOffset++]; + t0 = a0; t1 = a1; t2 = a2; + } + + // last round is special + int tt = K[keyOffset++]; + out[outOffset++] = (byte)(S[(t0 >>> 24) ] ^ (tt >>> 24)); + out[outOffset++] = (byte)(S[(t1 >>> 16) & 0xFF] ^ (tt >>> 16)); + out[outOffset++] = (byte)(S[(t2 >>> 8) & 0xFF] ^ (tt >>> 8)); + out[outOffset++] = (byte)(S[(t3 ) & 0xFF] ^ (tt )); + tt = K[keyOffset++]; + out[outOffset++] = (byte)(S[(t1 >>> 24) ] ^ (tt >>> 24)); + out[outOffset++] = (byte)(S[(t2 >>> 16) & 0xFF] ^ (tt >>> 16)); + out[outOffset++] = (byte)(S[(t3 >>> 8) & 0xFF] ^ (tt >>> 8)); + out[outOffset++] = (byte)(S[(t0 ) & 0xFF] ^ (tt )); + tt = K[keyOffset++]; + out[outOffset++] = (byte)(S[(t2 >>> 24) ] ^ (tt >>> 24)); + out[outOffset++] = (byte)(S[(t3 >>> 16) & 0xFF] ^ (tt >>> 16)); + out[outOffset++] = (byte)(S[(t0 >>> 8) & 0xFF] ^ (tt >>> 8)); + out[outOffset++] = (byte)(S[(t1 ) & 0xFF] ^ (tt )); + tt = K[keyOffset]; + out[outOffset++] = (byte)(S[(t3 >>> 24) ] ^ (tt >>> 24)); + out[outOffset++] = (byte)(S[(t0 >>> 16) & 0xFF] ^ (tt >>> 16)); + out[outOffset++] = (byte)(S[(t1 >>> 8) & 0xFF] ^ (tt >>> 8)); + out[outOffset ] = (byte)(S[(t2 ) & 0xFF] ^ (tt )); + } + + /** + * Decrypt exactly one block of plaintext. + */ + void decryptBlock(byte[] in, int inOffset, + byte[] out, int outOffset) { + // Array bound checks are done in caller code, i.e. + // FeedbackCipher.encrypt/decrypt(...) to improve performance. + implDecryptBlock(in, inOffset, out, outOffset); + } + + // Decrypt operation. Possibly replaced with a compiler intrinsic. + @IntrinsicCandidate + private void implDecryptBlock(byte[] in, int inOffset, + byte[] out, int outOffset) + { + int keyOffset = 4; + int t0 = ((in[inOffset++] ) << 24 | + (in[inOffset++] & 0xFF) << 16 | + (in[inOffset++] & 0xFF) << 8 | + (in[inOffset++] & 0xFF) ) ^ K[keyOffset++]; + int t1 = ((in[inOffset++] ) << 24 | + (in[inOffset++] & 0xFF) << 16 | + (in[inOffset++] & 0xFF) << 8 | + (in[inOffset++] & 0xFF) ) ^ K[keyOffset++]; + int t2 = ((in[inOffset++] ) << 24 | + (in[inOffset++] & 0xFF) << 16 | + (in[inOffset++] & 0xFF) << 8 | + (in[inOffset++] & 0xFF) ) ^ K[keyOffset++]; + int t3 = ((in[inOffset++] ) << 24 | + (in[inOffset++] & 0xFF) << 16 | + (in[inOffset++] & 0xFF) << 8 | + (in[inOffset ] & 0xFF) ) ^ K[keyOffset++]; + + int a0, a1, a2; + if(ROUNDS_12) + { + a0 = T5[(t0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ + T7[(t2>>> 8)&0xFF] ^ T8[(t1 )&0xFF] ^ K[keyOffset++]; + a1 = T5[(t1>>>24) ] ^ T6[(t0>>>16)&0xFF] ^ + T7[(t3>>> 8)&0xFF] ^ T8[(t2 )&0xFF] ^ K[keyOffset++]; + a2 = T5[(t2>>>24) ] ^ T6[(t1>>>16)&0xFF] ^ + T7[(t0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++]; + t3 = T5[(t3>>>24) ] ^ T6[(t2>>>16)&0xFF] ^ + T7[(t1>>> 8)&0xFF] ^ T8[(t0 )&0xFF] ^ K[keyOffset++]; + t0 = T5[(a0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ + T7[(a2>>> 8)&0xFF] ^ T8[(a1 )&0xFF] ^ K[keyOffset++]; + t1 = T5[(a1>>>24) ] ^ T6[(a0>>>16)&0xFF] ^ + T7[(t3>>> 8)&0xFF] ^ T8[(a2 )&0xFF] ^ K[keyOffset++]; + t2 = T5[(a2>>>24) ] ^ T6[(a1>>>16)&0xFF] ^ + T7[(a0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++]; + t3 = T5[(t3>>>24) ] ^ T6[(a2>>>16)&0xFF] ^ + T7[(a1>>> 8)&0xFF] ^ T8[(a0 )&0xFF] ^ K[keyOffset++]; + + if(ROUNDS_14) + { + a0 = T5[(t0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ + T7[(t2>>> 8)&0xFF] ^ T8[(t1 )&0xFF] ^ K[keyOffset++]; + a1 = T5[(t1>>>24) ] ^ T6[(t0>>>16)&0xFF] ^ + T7[(t3>>> 8)&0xFF] ^ T8[(t2 )&0xFF] ^ K[keyOffset++]; + a2 = T5[(t2>>>24) ] ^ T6[(t1>>>16)&0xFF] ^ + T7[(t0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++]; + t3 = T5[(t3>>>24) ] ^ T6[(t2>>>16)&0xFF] ^ + T7[(t1>>> 8)&0xFF] ^ T8[(t0 )&0xFF] ^ K[keyOffset++]; + t0 = T5[(a0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ + T7[(a2>>> 8)&0xFF] ^ T8[(a1 )&0xFF] ^ K[keyOffset++]; + t1 = T5[(a1>>>24) ] ^ T6[(a0>>>16)&0xFF] ^ + T7[(t3>>> 8)&0xFF] ^ T8[(a2 )&0xFF] ^ K[keyOffset++]; + t2 = T5[(a2>>>24) ] ^ T6[(a1>>>16)&0xFF] ^ + T7[(a0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++]; + t3 = T5[(t3>>>24) ] ^ T6[(a2>>>16)&0xFF] ^ + T7[(a1>>> 8)&0xFF] ^ T8[(a0 )&0xFF] ^ K[keyOffset++]; + } + } + a0 = T5[(t0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ + T7[(t2>>> 8)&0xFF] ^ T8[(t1 )&0xFF] ^ K[keyOffset++]; + a1 = T5[(t1>>>24) ] ^ T6[(t0>>>16)&0xFF] ^ + T7[(t3>>> 8)&0xFF] ^ T8[(t2 )&0xFF] ^ K[keyOffset++]; + a2 = T5[(t2>>>24) ] ^ T6[(t1>>>16)&0xFF] ^ + T7[(t0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++]; + t3 = T5[(t3>>>24) ] ^ T6[(t2>>>16)&0xFF] ^ + T7[(t1>>> 8)&0xFF] ^ T8[(t0 )&0xFF] ^ K[keyOffset++]; + t0 = T5[(a0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ + T7[(a2>>> 8)&0xFF] ^ T8[(a1 )&0xFF] ^ K[keyOffset++]; + t1 = T5[(a1>>>24) ] ^ T6[(a0>>>16)&0xFF] ^ + T7[(t3>>> 8)&0xFF] ^ T8[(a2 )&0xFF] ^ K[keyOffset++]; + t2 = T5[(a2>>>24) ] ^ T6[(a1>>>16)&0xFF] ^ + T7[(a0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++]; + t3 = T5[(t3>>>24) ] ^ T6[(a2>>>16)&0xFF] ^ + T7[(a1>>> 8)&0xFF] ^ T8[(a0 )&0xFF] ^ K[keyOffset++]; + a0 = T5[(t0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ + T7[(t2>>> 8)&0xFF] ^ T8[(t1 )&0xFF] ^ K[keyOffset++]; + a1 = T5[(t1>>>24) ] ^ T6[(t0>>>16)&0xFF] ^ + T7[(t3>>> 8)&0xFF] ^ T8[(t2 )&0xFF] ^ K[keyOffset++]; + a2 = T5[(t2>>>24) ] ^ T6[(t1>>>16)&0xFF] ^ + T7[(t0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++]; + t3 = T5[(t3>>>24) ] ^ T6[(t2>>>16)&0xFF] ^ + T7[(t1>>> 8)&0xFF] ^ T8[(t0 )&0xFF] ^ K[keyOffset++]; + t0 = T5[(a0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ + T7[(a2>>> 8)&0xFF] ^ T8[(a1 )&0xFF] ^ K[keyOffset++]; + t1 = T5[(a1>>>24) ] ^ T6[(a0>>>16)&0xFF] ^ + T7[(t3>>> 8)&0xFF] ^ T8[(a2 )&0xFF] ^ K[keyOffset++]; + t2 = T5[(a2>>>24) ] ^ T6[(a1>>>16)&0xFF] ^ + T7[(a0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++]; + t3 = T5[(t3>>>24) ] ^ T6[(a2>>>16)&0xFF] ^ + T7[(a1>>> 8)&0xFF] ^ T8[(a0 )&0xFF] ^ K[keyOffset++]; + a0 = T5[(t0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ + T7[(t2>>> 8)&0xFF] ^ T8[(t1 )&0xFF] ^ K[keyOffset++]; + a1 = T5[(t1>>>24) ] ^ T6[(t0>>>16)&0xFF] ^ + T7[(t3>>> 8)&0xFF] ^ T8[(t2 )&0xFF] ^ K[keyOffset++]; + a2 = T5[(t2>>>24) ] ^ T6[(t1>>>16)&0xFF] ^ + T7[(t0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++]; + t3 = T5[(t3>>>24) ] ^ T6[(t2>>>16)&0xFF] ^ + T7[(t1>>> 8)&0xFF] ^ T8[(t0 )&0xFF] ^ K[keyOffset++]; + t0 = T5[(a0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ + T7[(a2>>> 8)&0xFF] ^ T8[(a1 )&0xFF] ^ K[keyOffset++]; + t1 = T5[(a1>>>24) ] ^ T6[(a0>>>16)&0xFF] ^ + T7[(t3>>> 8)&0xFF] ^ T8[(a2 )&0xFF] ^ K[keyOffset++]; + t2 = T5[(a2>>>24) ] ^ T6[(a1>>>16)&0xFF] ^ + T7[(a0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++]; + t3 = T5[(t3>>>24) ] ^ T6[(a2>>>16)&0xFF] ^ + T7[(a1>>> 8)&0xFF] ^ T8[(a0 )&0xFF] ^ K[keyOffset++]; + a0 = T5[(t0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ + T7[(t2>>> 8)&0xFF] ^ T8[(t1 )&0xFF] ^ K[keyOffset++]; + a1 = T5[(t1>>>24) ] ^ T6[(t0>>>16)&0xFF] ^ + T7[(t3>>> 8)&0xFF] ^ T8[(t2 )&0xFF] ^ K[keyOffset++]; + a2 = T5[(t2>>>24) ] ^ T6[(t1>>>16)&0xFF] ^ + T7[(t0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++]; + t3 = T5[(t3>>>24) ] ^ T6[(t2>>>16)&0xFF] ^ + T7[(t1>>> 8)&0xFF] ^ T8[(t0 )&0xFF] ^ K[keyOffset++]; + t0 = T5[(a0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ + T7[(a2>>> 8)&0xFF] ^ T8[(a1 )&0xFF] ^ K[keyOffset++]; + t1 = T5[(a1>>>24) ] ^ T6[(a0>>>16)&0xFF] ^ + T7[(t3>>> 8)&0xFF] ^ T8[(a2 )&0xFF] ^ K[keyOffset++]; + t2 = T5[(a2>>>24) ] ^ T6[(a1>>>16)&0xFF] ^ + T7[(a0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++]; + t3 = T5[(t3>>>24) ] ^ T6[(a2>>>16)&0xFF] ^ + T7[(a1>>> 8)&0xFF] ^ T8[(a0 )&0xFF] ^ K[keyOffset++]; + a0 = T5[(t0>>>24) ] ^ T6[(t3>>>16)&0xFF] ^ + T7[(t2>>> 8)&0xFF] ^ T8[(t1 )&0xFF] ^ K[keyOffset++]; + a1 = T5[(t1>>>24) ] ^ T6[(t0>>>16)&0xFF] ^ + T7[(t3>>> 8)&0xFF] ^ T8[(t2 )&0xFF] ^ K[keyOffset++]; + a2 = T5[(t2>>>24) ] ^ T6[(t1>>>16)&0xFF] ^ + T7[(t0>>> 8)&0xFF] ^ T8[(t3 )&0xFF] ^ K[keyOffset++]; + t3 = T5[(t3>>>24) ] ^ T6[(t2>>>16)&0xFF] ^ + T7[(t1>>> 8)&0xFF] ^ T8[(t0 )&0xFF] ^ K[keyOffset]; + + t1 = K[0]; + out[outOffset++] = (byte)(Si[(a0 >>> 24) ] ^ (t1 >>> 24)); + out[outOffset++] = (byte)(Si[(t3 >>> 16) & 0xFF] ^ (t1 >>> 16)); + out[outOffset++] = (byte)(Si[(a2 >>> 8) & 0xFF] ^ (t1 >>> 8)); + out[outOffset++] = (byte)(Si[(a1 ) & 0xFF] ^ (t1 )); + t1 = K[1]; + out[outOffset++] = (byte)(Si[(a1 >>> 24) ] ^ (t1 >>> 24)); + out[outOffset++] = (byte)(Si[(a0 >>> 16) & 0xFF] ^ (t1 >>> 16)); + out[outOffset++] = (byte)(Si[(t3 >>> 8) & 0xFF] ^ (t1 >>> 8)); + out[outOffset++] = (byte)(Si[(a2 ) & 0xFF] ^ (t1 )); + t1 = K[2]; + out[outOffset++] = (byte)(Si[(a2 >>> 24) ] ^ (t1 >>> 24)); + out[outOffset++] = (byte)(Si[(a1 >>> 16) & 0xFF] ^ (t1 >>> 16)); + out[outOffset++] = (byte)(Si[(a0 >>> 8) & 0xFF] ^ (t1 >>> 8)); + out[outOffset++] = (byte)(Si[(t3 ) & 0xFF] ^ (t1 )); + t1 = K[3]; + out[outOffset++] = (byte)(Si[(t3 >>> 24) ] ^ (t1 >>> 24)); + out[outOffset++] = (byte)(Si[(a2 >>> 16) & 0xFF] ^ (t1 >>> 16)); + out[outOffset++] = (byte)(Si[(a1 >>> 8) & 0xFF] ^ (t1 >>> 8)); + out[outOffset ] = (byte)(Si[(a0 ) & 0xFF] ^ (t1 )); + } + + /** + * Expand a user-supplied key material into a session key. + * + * @param k The 128/192/256-bit cipher key to use. + * @exception InvalidKeyException If the key is invalid. + */ + private void makeSessionKey(byte[] k) throws InvalidKeyException { + if (!isKeySizeValid(k.length)) { + throw new InvalidKeyException("Invalid AES key length: " + + k.length + " bytes"); + } + + final int BC = 4; + + int ROUNDS = getRounds(k.length); + int ROUND_KEY_COUNT = (ROUNDS + 1) * BC; + + int[] Ke = new int[ROUND_KEY_COUNT]; // encryption round keys + int[] Kd = new int[ROUND_KEY_COUNT]; // decryption round keys + + int KC = k.length/4; // keylen in 32-bit elements + + int[] tk = new int[KC]; + int i, j; + + // copy user material bytes into temporary ints + for (i = 0, j = 0; i < KC; i++, j+=4) { + tk[i] = (k[j] ) << 24 | + (k[j+1] & 0xFF) << 16 | + (k[j+2] & 0xFF) << 8 | + (k[j+3] & 0xFF); + } + + // copy values into round key arrays + int t = 0; + for (j = 0; (j < KC) && (t < ROUND_KEY_COUNT); j++, t++) { + Ke[t] = tk[j]; + Kd[(ROUNDS - (t / BC))*BC + (t % BC)] = tk[j]; + } + int tt, rconpointer = 0; + while (t < ROUND_KEY_COUNT) { + // extrapolate using phi (the round key evolution function) + tt = tk[KC - 1]; + tk[0] ^= (S[(tt >>> 16) & 0xFF] ) << 24 ^ + (S[(tt >>> 8) & 0xFF] & 0xFF) << 16 ^ + (S[(tt ) & 0xFF] & 0xFF) << 8 ^ + (S[(tt >>> 24) ] & 0xFF) ^ + (rcon[rconpointer++] ) << 24; + if (KC != 8) + for (i = 1, j = 0; i < KC; i++, j++) tk[i] ^= tk[j]; + else { + for (i = 1, j = 0; i < KC / 2; i++, j++) tk[i] ^= tk[j]; + tt = tk[KC / 2 - 1]; + tk[KC / 2] ^= (S[(tt ) & 0xFF] & 0xFF) ^ + (S[(tt >>> 8) & 0xFF] & 0xFF) << 8 ^ + (S[(tt >>> 16) & 0xFF] & 0xFF) << 16 ^ + (S[(tt >>> 24) ] ) << 24; + for (j = KC / 2, i = j + 1; i < KC; i++, j++) tk[i] ^= tk[j]; + } + // copy values into round key arrays + for (j = 0; (j < KC) && (t < ROUND_KEY_COUNT); j++, t++) { + Ke[t] = tk[j]; + Kd[(ROUNDS - (t / BC))*BC + (t % BC)] = tk[j]; + } + } + for (int r = 1; r < ROUNDS; r++) { + // inverse MixColumn where needed + for (j = 0; j < BC; j++) { + int idx = r*BC + j; + tt = Kd[idx]; + Kd[idx] = U1[(tt >>> 24) & 0xFF] ^ + U2[(tt >>> 16) & 0xFF] ^ + U3[(tt >>> 8) & 0xFF] ^ + U4[ tt & 0xFF]; + } + } + + // For decryption round keys, need to rotate right by 4 ints. + // Do that without allocating and zeroing the small buffer. + int KdTail_0 = Kd[Kd.length - 4]; + int KdTail_1 = Kd[Kd.length - 3]; + int KdTail_2 = Kd[Kd.length - 2]; + int KdTail_3 = Kd[Kd.length - 1]; + System.arraycopy(Kd, 0, Kd, 4, Kd.length - 4); + Kd[0] = KdTail_0; + Kd[1] = KdTail_1; + Kd[2] = KdTail_2; + Kd[3] = KdTail_3; + + Arrays.fill(tk, 0); + ROUNDS_12 = (ROUNDS>=12); + ROUNDS_14 = (ROUNDS==14); + limit = ROUNDS*4; + + // store the expanded sub keys into 'sessionK' + if (sessionK != null) { + // erase the previous values in sessionK + Arrays.fill(sessionK[0], 0); + Arrays.fill(sessionK[1], 0); + } else { + sessionK = new int[2][]; + } + sessionK[0] = Ke; + sessionK[1] = Kd; + } + + /** + * Return The number of rounds for a given Rijndael keysize. + * + * @param keySize The size of the user key material in bytes. + * MUST be one of (16, 24, 32). + * @return The number of rounds. + */ + private static int getRounds(int keySize) { + return (keySize >> 2) + 6; + } +} diff --git a/src/java.base/share/classes/com/sun/crypto/provider/AESKeyGenerator.java b/src/java.base/share/classes/com/sun/crypto/provider/AESKeyGenerator.java index 915d329d33d67..51671fdf25d0a 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/AESKeyGenerator.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/AESKeyGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -91,7 +91,7 @@ protected void engineInit(AlgorithmParameterSpec params, */ protected void engineInit(int keysize, SecureRandom random) { if (((keysize % 8) != 0) || - (!AES_Crypt.isKeySizeValid(keysize/8))) { + (!AESCrypt.isKeySizeValid(keysize/8))) { throw new InvalidParameterException ("Wrong keysize: must be equal to 128, 192 or 256"); } diff --git a/src/java.base/share/classes/com/sun/crypto/provider/AESKeyWrap.java b/src/java.base/share/classes/com/sun/crypto/provider/AESKeyWrap.java index 2828183802f8f..7ba4420f97348 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/AESKeyWrap.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/AESKeyWrap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,7 +50,7 @@ class AESKeyWrap extends FeedbackCipher { }; AESKeyWrap() { - super(new AES_Crypt()); + super(new AESCrypt()); } /** diff --git a/src/java.base/share/classes/com/sun/crypto/provider/AESKeyWrapPadded.java b/src/java.base/share/classes/com/sun/crypto/provider/AESKeyWrapPadded.java index f6fec405b2fc6..4f25849d8501b 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/AESKeyWrapPadded.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/AESKeyWrapPadded.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -87,7 +87,7 @@ private static int validateIV(byte[] ivAndLen, byte[] iv) } AESKeyWrapPadded() { - super(new AES_Crypt()); + super(new AESCrypt()); } /** diff --git a/src/java.base/share/classes/com/sun/crypto/provider/AES_Crypt.java b/src/java.base/share/classes/com/sun/crypto/provider/AES_Crypt.java deleted file mode 100644 index 6e3e6144affc9..0000000000000 --- a/src/java.base/share/classes/com/sun/crypto/provider/AES_Crypt.java +++ /dev/null @@ -1,1392 +0,0 @@ -/* - * 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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 com.sun.crypto.provider; - -import java.security.InvalidKeyException; -import java.security.MessageDigest; -import java.util.Arrays; - -import jdk.internal.vm.annotation.IntrinsicCandidate; - -/** - * Implementation of the AES cipher, which is based on the following documents: - * - * @spec https://csrc.nist.gov/csrc/media/projects/cryptographic-standards-and-guidelines/documents/aes-development/rijndael-ammended.pdf - * - * @spec https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.197-upd1.pdf - * - * https://www.internationaljournalcorner.com/index.php/ijird_ojs/article/view/134688 - */ -final class AES_Crypt extends SymmetricCipher { - - // Number of words in a block - private static final int WB = 4; - // Number of bytes in a word - private static final int BW = 4; - - private static final int AES_128_ROUNDS = 10; - private static final int AES_192_ROUNDS = 12; - private static final int AES_256_ROUNDS = 14; - - private int rounds; - private byte[] prevKey = null; - - // Following two attributes are specific to Intrinsics where sessionK is - // used for PPC64, S390, and RISCV64 architectures, whereas K is used for - // everything else. - private int[][] sessionK = null; - private int[] K = null; - - // Round constant - private static final int[] RCON = { - 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, - 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000, - }; - - private static final byte[][] SBOX = { - { (byte)0x63, (byte)0x7C, (byte)0x77, (byte)0x7B, (byte)0xF2, - (byte)0x6B, (byte)0x6F, (byte)0xC5, (byte)0x30, (byte)0x01, - (byte)0x67, (byte)0x2B, (byte)0xFE, (byte)0xD7, (byte)0xAB, - (byte)0x76 }, - { (byte)0xCA, (byte)0x82, (byte)0xC9, (byte)0x7D, (byte)0xFA, - (byte)0x59, (byte)0x47, (byte)0xF0, (byte)0xAD, (byte)0xD4, - (byte)0xA2, (byte)0xAF, (byte)0x9C, (byte)0xA4, (byte)0x72, - (byte)0xC0 }, - { (byte)0xB7, (byte)0xFD, (byte)0x93, (byte)0x26, (byte)0x36, - (byte)0x3F, (byte)0xF7, (byte)0xCC, (byte)0x34, (byte)0xA5, - (byte)0xE5, (byte)0xF1, (byte)0x71, (byte)0xD8, (byte)0x31, - (byte)0x15 }, - { (byte)0x04, (byte)0xC7, (byte)0x23, (byte)0xC3, (byte)0x18, - (byte)0x96, (byte)0x05, (byte)0x9A, (byte)0x07, (byte)0x12, - (byte)0x80, (byte)0xE2, (byte)0xEB, (byte)0x27, (byte)0xB2, - (byte)0x75 }, - { (byte)0x09, (byte)0x83, (byte)0x2C, (byte)0x1A, (byte)0x1B, - (byte)0x6E, (byte)0x5A, (byte)0xA0, (byte)0x52, (byte)0x3B, - (byte)0xD6, (byte)0xB3, (byte)0x29, (byte)0xE3, (byte)0x2F, - (byte)0x84 }, - { (byte)0x53, (byte)0xD1, (byte)0x00, (byte)0xED, (byte)0x20, - (byte)0xFC, (byte)0xB1, (byte)0x5B, (byte)0x6A, (byte)0xCB, - (byte)0xBE, (byte)0x39, (byte)0x4A, (byte)0x4C, (byte)0x58, - (byte)0xCF }, - { (byte)0xD0, (byte)0xEF, (byte)0xAA, (byte)0xFB, (byte)0x43, - (byte)0x4D, (byte)0x33, (byte)0x85, (byte)0x45, (byte)0xF9, - (byte)0x02, (byte)0x7F, (byte)0x50, (byte)0x3C, (byte)0x9F, - (byte)0xA8 }, - { (byte)0x51, (byte)0xA3, (byte)0x40, (byte)0x8F, (byte)0x92, - (byte)0x9D, (byte)0x38, (byte)0xF5, (byte)0xBC, (byte)0xB6, - (byte)0xDA, (byte)0x21, (byte)0x10, (byte)0xFF, (byte)0xF3, - (byte)0xD2 }, - { (byte)0xCD, (byte)0x0C, (byte)0x13, (byte)0xEC, (byte)0x5F, - (byte)0x97, (byte)0x44, (byte)0x17, (byte)0xC4, (byte)0xA7, - (byte)0x7E, (byte)0x3D, (byte)0x64, (byte)0x5D, (byte)0x19, - (byte)0x73 }, - { (byte)0x60, (byte)0x81, (byte)0x4F, (byte)0xDC, (byte)0x22, - (byte)0x2A, (byte)0x90, (byte)0x88, (byte)0x46, (byte)0xEE, - (byte)0xB8, (byte)0x14, (byte)0xDE, (byte)0x5E, (byte)0x0B, - (byte)0xDB }, - { (byte)0xE0, (byte)0x32, (byte)0x3A, (byte)0x0A, (byte)0x49, - (byte)0x06, (byte)0x24, (byte)0x5C, (byte)0xC2, (byte)0xD3, - (byte)0xAC, (byte)0x62, (byte)0x91, (byte)0x95, (byte)0xE4, - (byte)0x79 }, - { (byte)0xE7, (byte)0xC8, (byte)0x37, (byte)0x6D, (byte)0x8D, - (byte)0xD5, (byte)0x4E, (byte)0xA9, (byte)0x6C, (byte)0x56, - (byte)0xF4, (byte)0xEA, (byte)0x65, (byte)0x7A, (byte)0xAE, - (byte)0x08 }, - { (byte)0xBA, (byte)0x78, (byte)0x25, (byte)0x2E, (byte)0x1C, - (byte)0xA6, (byte)0xB4, (byte)0xC6, (byte)0xE8, (byte)0xDD, - (byte)0x74, (byte)0x1F, (byte)0x4B, (byte)0xBD, (byte)0x8B, - (byte)0x8A }, - { (byte)0x70, (byte)0x3E, (byte)0xB5, (byte)0x66, (byte)0x48, - (byte)0x03, (byte)0xF6, (byte)0x0E, (byte)0x61, (byte)0x35, - (byte)0x57, (byte)0xB9, (byte)0x86, (byte)0xC1, (byte)0x1D, - (byte)0x9E }, - { (byte)0xE1, (byte)0xF8, (byte)0x98, (byte)0x11, (byte)0x69, - (byte)0xD9, (byte)0x8E, (byte)0x94, (byte)0x9B, (byte)0x1E, - (byte)0x87, (byte)0xE9, (byte)0xCE, (byte)0x55, (byte)0x28, - (byte)0xDF }, - { (byte)0x8C, (byte)0xA1, (byte)0x89, (byte)0x0D, (byte)0xBF, - (byte)0xE6, (byte)0x42, (byte)0x68, (byte)0x41, (byte)0x99, - (byte)0x2D, (byte)0x0F, (byte)0xB0, (byte)0x54, (byte)0xBB, - (byte)0x16 } - }; - - // Lookup table for row 0 transforms, see section 5.2.1 of original spec. - private static final int[] T0 = { - 0xC66363A5, 0xF87C7C84, 0xEE777799, 0xF67B7B8D, 0xFFF2F20D, - 0xD66B6BBD, 0xDE6F6FB1, 0x91C5C554, 0x60303050, 0x02010103, - 0xCE6767A9, 0x562B2B7D, 0xE7FEFE19, 0xB5D7D762, 0x4DABABE6, - 0xEC76769A, 0x8FCACA45, 0x1F82829D, 0x89C9C940, 0xFA7D7D87, - 0xEFFAFA15, 0xB25959EB, 0x8E4747C9, 0xFBF0F00B, 0x41ADADEC, - 0xB3D4D467, 0x5FA2A2FD, 0x45AFAFEA, 0x239C9CBF, 0x53A4A4F7, - 0xE4727296, 0x9BC0C05B, 0x75B7B7C2, 0xE1FDFD1C, 0x3D9393AE, - 0x4C26266A, 0x6C36365A, 0x7E3F3F41, 0xF5F7F702, 0x83CCCC4F, - 0x6834345C, 0x51A5A5F4, 0xD1E5E534, 0xF9F1F108, 0xE2717193, - 0xABD8D873, 0x62313153, 0x2A15153F, 0x0804040C, 0x95C7C752, - 0x46232365, 0x9DC3C35E, 0x30181828, 0x379696A1, 0x0A05050F, - 0x2F9A9AB5, 0x0E070709, 0x24121236, 0x1B80809B, 0xDFE2E23D, - 0xCDEBEB26, 0x4E272769, 0x7FB2B2CD, 0xEA75759F, 0x1209091B, - 0x1D83839E, 0x582C2C74, 0x341A1A2E, 0x361B1B2D, 0xDC6E6EB2, - 0xB45A5AEE, 0x5BA0A0FB, 0xA45252F6, 0x763B3B4D, 0xB7D6D661, - 0x7DB3B3CE, 0x5229297B, 0xDDE3E33E, 0x5E2F2F71, 0x13848497, - 0xA65353F5, 0xB9D1D168, 0x00000000, 0xC1EDED2C, 0x40202060, - 0xE3FCFC1F, 0x79B1B1C8, 0xB65B5BED, 0xD46A6ABE, 0x8DCBCB46, - 0x67BEBED9, 0x7239394B, 0x944A4ADE, 0x984C4CD4, 0xB05858E8, - 0x85CFCF4A, 0xBBD0D06B, 0xC5EFEF2A, 0x4FAAAAE5, 0xEDFBFB16, - 0x864343C5, 0x9A4D4DD7, 0x66333355, 0x11858594, 0x8A4545CF, - 0xE9F9F910, 0x04020206, 0xFE7F7F81, 0xA05050F0, 0x783C3C44, - 0x259F9FBA, 0x4BA8A8E3, 0xA25151F3, 0x5DA3A3FE, 0x804040C0, - 0x058F8F8A, 0x3F9292AD, 0x219D9DBC, 0x70383848, 0xF1F5F504, - 0x63BCBCDF, 0x77B6B6C1, 0xAFDADA75, 0x42212163, 0x20101030, - 0xE5FFFF1A, 0xFDF3F30E, 0xBFD2D26D, 0x81CDCD4C, 0x180C0C14, - 0x26131335, 0xC3ECEC2F, 0xBE5F5FE1, 0x359797A2, 0x884444CC, - 0x2E171739, 0x93C4C457, 0x55A7A7F2, 0xFC7E7E82, 0x7A3D3D47, - 0xC86464AC, 0xBA5D5DE7, 0x3219192B, 0xE6737395, 0xC06060A0, - 0x19818198, 0x9E4F4FD1, 0xA3DCDC7F, 0x44222266, 0x542A2A7E, - 0x3B9090AB, 0x0B888883, 0x8C4646CA, 0xC7EEEE29, 0x6BB8B8D3, - 0x2814143C, 0xA7DEDE79, 0xBC5E5EE2, 0x160B0B1D, 0xADDBDB76, - 0xDBE0E03B, 0x64323256, 0x743A3A4E, 0x140A0A1E, 0x924949DB, - 0x0C06060A, 0x4824246C, 0xB85C5CE4, 0x9FC2C25D, 0xBDD3D36E, - 0x43ACACEF, 0xC46262A6, 0x399191A8, 0x319595A4, 0xD3E4E437, - 0xF279798B, 0xD5E7E732, 0x8BC8C843, 0x6E373759, 0xDA6D6DB7, - 0x018D8D8C, 0xB1D5D564, 0x9C4E4ED2, 0x49A9A9E0, 0xD86C6CB4, - 0xAC5656FA, 0xF3F4F407, 0xCFEAEA25, 0xCA6565AF, 0xF47A7A8E, - 0x47AEAEE9, 0x10080818, 0x6FBABAD5, 0xF0787888, 0x4A25256F, - 0x5C2E2E72, 0x381C1C24, 0x57A6A6F1, 0x73B4B4C7, 0x97C6C651, - 0xCBE8E823, 0xA1DDDD7C, 0xE874749C, 0x3E1F1F21, 0x964B4BDD, - 0x61BDBDDC, 0x0D8B8B86, 0x0F8A8A85, 0xE0707090, 0x7C3E3E42, - 0x71B5B5C4, 0xCC6666AA, 0x904848D8, 0x06030305, 0xF7F6F601, - 0x1C0E0E12, 0xC26161A3, 0x6A35355F, 0xAE5757F9, 0x69B9B9D0, - 0x17868691, 0x99C1C158, 0x3A1D1D27, 0x279E9EB9, 0xD9E1E138, - 0xEBF8F813, 0x2B9898B3, 0x22111133, 0xD26969BB, 0xA9D9D970, - 0x078E8E89, 0x339494A7, 0x2D9B9BB6, 0x3C1E1E22, 0x15878792, - 0xC9E9E920, 0x87CECE49, 0xAA5555FF, 0x50282878, 0xA5DFDF7A, - 0x038C8C8F, 0x59A1A1F8, 0x09898980, 0x1A0D0D17, 0x65BFBFDA, - 0xD7E6E631, 0x844242C6, 0xD06868B8, 0x824141C3, 0x299999B0, - 0x5A2D2D77, 0x1E0F0F11, 0x7BB0B0CB, 0xA85454FC, 0x6DBBBBD6, - 0x2C16163A, - }; - - // Lookup table for row 1 transforms, see section 5.2.1 of original spec. - private static final int[] T1 = { - 0xA5C66363, 0x84F87C7C, 0x99EE7777, 0x8DF67B7B, 0x0DFFF2F2, - 0xBDD66B6B, 0xB1DE6F6F, 0x5491C5C5, 0x50603030, 0x03020101, - 0xA9CE6767, 0x7D562B2B, 0x19E7FEFE, 0x62B5D7D7, 0xE64DABAB, - 0x9AEC7676, 0x458FCACA, 0x9D1F8282, 0x4089C9C9, 0x87FA7D7D, - 0x15EFFAFA, 0xEBB25959, 0xC98E4747, 0x0BFBF0F0, 0xEC41ADAD, - 0x67B3D4D4, 0xFD5FA2A2, 0xEA45AFAF, 0xBF239C9C, 0xF753A4A4, - 0x96E47272, 0x5B9BC0C0, 0xC275B7B7, 0x1CE1FDFD, 0xAE3D9393, - 0x6A4C2626, 0x5A6C3636, 0x417E3F3F, 0x02F5F7F7, 0x4F83CCCC, - 0x5C683434, 0xF451A5A5, 0x34D1E5E5, 0x08F9F1F1, 0x93E27171, - 0x73ABD8D8, 0x53623131, 0x3F2A1515, 0x0C080404, 0x5295C7C7, - 0x65462323, 0x5E9DC3C3, 0x28301818, 0xA1379696, 0x0F0A0505, - 0xB52F9A9A, 0x090E0707, 0x36241212, 0x9B1B8080, 0x3DDFE2E2, - 0x26CDEBEB, 0x694E2727, 0xCD7FB2B2, 0x9FEA7575, 0x1B120909, - 0x9E1D8383, 0x74582C2C, 0x2E341A1A, 0x2D361B1B, 0xB2DC6E6E, - 0xEEB45A5A, 0xFB5BA0A0, 0xF6A45252, 0x4D763B3B, 0x61B7D6D6, - 0xCE7DB3B3, 0x7B522929, 0x3EDDE3E3, 0x715E2F2F, 0x97138484, - 0xF5A65353, 0x68B9D1D1, 0x00000000, 0x2CC1EDED, 0x60402020, - 0x1FE3FCFC, 0xC879B1B1, 0xEDB65B5B, 0xBED46A6A, 0x468DCBCB, - 0xD967BEBE, 0x4B723939, 0xDE944A4A, 0xD4984C4C, 0xE8B05858, - 0x4A85CFCF, 0x6BBBD0D0, 0x2AC5EFEF, 0xE54FAAAA, 0x16EDFBFB, - 0xC5864343, 0xD79A4D4D, 0x55663333, 0x94118585, 0xCF8A4545, - 0x10E9F9F9, 0x06040202, 0x81FE7F7F, 0xF0A05050, 0x44783C3C, - 0xBA259F9F, 0xE34BA8A8, 0xF3A25151, 0xFE5DA3A3, 0xC0804040, - 0x8A058F8F, 0xAD3F9292, 0xBC219D9D, 0x48703838, 0x04F1F5F5, - 0xDF63BCBC, 0xC177B6B6, 0x75AFDADA, 0x63422121, 0x30201010, - 0x1AE5FFFF, 0x0EFDF3F3, 0x6DBFD2D2, 0x4C81CDCD, 0x14180C0C, - 0x35261313, 0x2FC3ECEC, 0xE1BE5F5F, 0xA2359797, 0xCC884444, - 0x392E1717, 0x5793C4C4, 0xF255A7A7, 0x82FC7E7E, 0x477A3D3D, - 0xACC86464, 0xE7BA5D5D, 0x2B321919, 0x95E67373, 0xA0C06060, - 0x98198181, 0xD19E4F4F, 0x7FA3DCDC, 0x66442222, 0x7E542A2A, - 0xAB3B9090, 0x830B8888, 0xCA8C4646, 0x29C7EEEE, 0xD36BB8B8, - 0x3C281414, 0x79A7DEDE, 0xE2BC5E5E, 0x1D160B0B, 0x76ADDBDB, - 0x3BDBE0E0, 0x56643232, 0x4E743A3A, 0x1E140A0A, 0xDB924949, - 0x0A0C0606, 0x6C482424, 0xE4B85C5C, 0x5D9FC2C2, 0x6EBDD3D3, - 0xEF43ACAC, 0xA6C46262, 0xA8399191, 0xA4319595, 0x37D3E4E4, - 0x8BF27979, 0x32D5E7E7, 0x438BC8C8, 0x596E3737, 0xB7DA6D6D, - 0x8C018D8D, 0x64B1D5D5, 0xD29C4E4E, 0xE049A9A9, 0xB4D86C6C, - 0xFAAC5656, 0x07F3F4F4, 0x25CFEAEA, 0xAFCA6565, 0x8EF47A7A, - 0xE947AEAE, 0x18100808, 0xD56FBABA, 0x88F07878, 0x6F4A2525, - 0x725C2E2E, 0x24381C1C, 0xF157A6A6, 0xC773B4B4, 0x5197C6C6, - 0x23CBE8E8, 0x7CA1DDDD, 0x9CE87474, 0x213E1F1F, 0xDD964B4B, - 0xDC61BDBD, 0x860D8B8B, 0x850F8A8A, 0x90E07070, 0x427C3E3E, - 0xC471B5B5, 0xAACC6666, 0xD8904848, 0x05060303, 0x01F7F6F6, - 0x121C0E0E, 0xA3C26161, 0x5F6A3535, 0xF9AE5757, 0xD069B9B9, - 0x91178686, 0x5899C1C1, 0x273A1D1D, 0xB9279E9E, 0x38D9E1E1, - 0x13EBF8F8, 0xB32B9898, 0x33221111, 0xBBD26969, 0x70A9D9D9, - 0x89078E8E, 0xA7339494, 0xB62D9B9B, 0x223C1E1E, 0x92158787, - 0x20C9E9E9, 0x4987CECE, 0xFFAA5555, 0x78502828, 0x7AA5DFDF, - 0x8F038C8C, 0xF859A1A1, 0x80098989, 0x171A0D0D, 0xDA65BFBF, - 0x31D7E6E6, 0xC6844242, 0xB8D06868, 0xC3824141, 0xB0299999, - 0x775A2D2D, 0x111E0F0F, 0xCB7BB0B0, 0xFCA85454, 0xD66DBBBB, - 0x3A2C1616, - }; - - // Lookup table for row 2 transforms, see section 5.2.1 of original spec. - private static final int[] T2 = { - 0x63A5C663, 0x7C84F87C, 0x7799EE77, 0x7B8DF67B, 0xF20DFFF2, - 0x6BBDD66B, 0x6FB1DE6F, 0xC55491C5, 0x30506030, 0x01030201, - 0x67A9CE67, 0x2B7D562B, 0xFE19E7FE, 0xD762B5D7, 0xABE64DAB, - 0x769AEC76, 0xCA458FCA, 0x829D1F82, 0xC94089C9, 0x7D87FA7D, - 0xFA15EFFA, 0x59EBB259, 0x47C98E47, 0xF00BFBF0, 0xADEC41AD, - 0xD467B3D4, 0xA2FD5FA2, 0xAFEA45AF, 0x9CBF239C, 0xA4F753A4, - 0x7296E472, 0xC05B9BC0, 0xB7C275B7, 0xFD1CE1FD, 0x93AE3D93, - 0x266A4C26, 0x365A6C36, 0x3F417E3F, 0xF702F5F7, 0xCC4F83CC, - 0x345C6834, 0xA5F451A5, 0xE534D1E5, 0xF108F9F1, 0x7193E271, - 0xD873ABD8, 0x31536231, 0x153F2A15, 0x040C0804, 0xC75295C7, - 0x23654623, 0xC35E9DC3, 0x18283018, 0x96A13796, 0x050F0A05, - 0x9AB52F9A, 0x07090E07, 0x12362412, 0x809B1B80, 0xE23DDFE2, - 0xEB26CDEB, 0x27694E27, 0xB2CD7FB2, 0x759FEA75, 0x091B1209, - 0x839E1D83, 0x2C74582C, 0x1A2E341A, 0x1B2D361B, 0x6EB2DC6E, - 0x5AEEB45A, 0xA0FB5BA0, 0x52F6A452, 0x3B4D763B, 0xD661B7D6, - 0xB3CE7DB3, 0x297B5229, 0xE33EDDE3, 0x2F715E2F, 0x84971384, - 0x53F5A653, 0xD168B9D1, 0x00000000, 0xED2CC1ED, 0x20604020, - 0xFC1FE3FC, 0xB1C879B1, 0x5BEDB65B, 0x6ABED46A, 0xCB468DCB, - 0xBED967BE, 0x394B7239, 0x4ADE944A, 0x4CD4984C, 0x58E8B058, - 0xCF4A85CF, 0xD06BBBD0, 0xEF2AC5EF, 0xAAE54FAA, 0xFB16EDFB, - 0x43C58643, 0x4DD79A4D, 0x33556633, 0x85941185, 0x45CF8A45, - 0xF910E9F9, 0x02060402, 0x7F81FE7F, 0x50F0A050, 0x3C44783C, - 0x9FBA259F, 0xA8E34BA8, 0x51F3A251, 0xA3FE5DA3, 0x40C08040, - 0x8F8A058F, 0x92AD3F92, 0x9DBC219D, 0x38487038, 0xF504F1F5, - 0xBCDF63BC, 0xB6C177B6, 0xDA75AFDA, 0x21634221, 0x10302010, - 0xFF1AE5FF, 0xF30EFDF3, 0xD26DBFD2, 0xCD4C81CD, 0x0C14180C, - 0x13352613, 0xEC2FC3EC, 0x5FE1BE5F, 0x97A23597, 0x44CC8844, - 0x17392E17, 0xC45793C4, 0xA7F255A7, 0x7E82FC7E, 0x3D477A3D, - 0x64ACC864, 0x5DE7BA5D, 0x192B3219, 0x7395E673, 0x60A0C060, - 0x81981981, 0x4FD19E4F, 0xDC7FA3DC, 0x22664422, 0x2A7E542A, - 0x90AB3B90, 0x88830B88, 0x46CA8C46, 0xEE29C7EE, 0xB8D36BB8, - 0x143C2814, 0xDE79A7DE, 0x5EE2BC5E, 0x0B1D160B, 0xDB76ADDB, - 0xE03BDBE0, 0x32566432, 0x3A4E743A, 0x0A1E140A, 0x49DB9249, - 0x060A0C06, 0x246C4824, 0x5CE4B85C, 0xC25D9FC2, 0xD36EBDD3, - 0xACEF43AC, 0x62A6C462, 0x91A83991, 0x95A43195, 0xE437D3E4, - 0x798BF279, 0xE732D5E7, 0xC8438BC8, 0x37596E37, 0x6DB7DA6D, - 0x8D8C018D, 0xD564B1D5, 0x4ED29C4E, 0xA9E049A9, 0x6CB4D86C, - 0x56FAAC56, 0xF407F3F4, 0xEA25CFEA, 0x65AFCA65, 0x7A8EF47A, - 0xAEE947AE, 0x08181008, 0xBAD56FBA, 0x7888F078, 0x256F4A25, - 0x2E725C2E, 0x1C24381C, 0xA6F157A6, 0xB4C773B4, 0xC65197C6, - 0xE823CBE8, 0xDD7CA1DD, 0x749CE874, 0x1F213E1F, 0x4BDD964B, - 0xBDDC61BD, 0x8B860D8B, 0x8A850F8A, 0x7090E070, 0x3E427C3E, - 0xB5C471B5, 0x66AACC66, 0x48D89048, 0x03050603, 0xF601F7F6, - 0x0E121C0E, 0x61A3C261, 0x355F6A35, 0x57F9AE57, 0xB9D069B9, - 0x86911786, 0xC15899C1, 0x1D273A1D, 0x9EB9279E, 0xE138D9E1, - 0xF813EBF8, 0x98B32B98, 0x11332211, 0x69BBD269, 0xD970A9D9, - 0x8E89078E, 0x94A73394, 0x9BB62D9B, 0x1E223C1E, 0x87921587, - 0xE920C9E9, 0xCE4987CE, 0x55FFAA55, 0x28785028, 0xDF7AA5DF, - 0x8C8F038C, 0xA1F859A1, 0x89800989, 0x0D171A0D, 0xBFDA65BF, - 0xE631D7E6, 0x42C68442, 0x68B8D068, 0x41C38241, 0x99B02999, - 0x2D775A2D, 0x0F111E0F, 0xB0CB7BB0, 0x54FCA854, 0xBBD66DBB, - 0x163A2C16, - }; - - // Lookup table for row 3 transforms, see section 5.2.1 of original spec. - private static final int[] T3 = { - 0x6363A5C6, 0x7C7C84F8, 0x777799EE, 0x7B7B8DF6, 0xF2F20DFF, - 0x6B6BBDD6, 0x6F6FB1DE, 0xC5C55491, 0x30305060, 0x01010302, - 0x6767A9CE, 0x2B2B7D56, 0xFEFE19E7, 0xD7D762B5, 0xABABE64D, - 0x76769AEC, 0xCACA458F, 0x82829D1F, 0xC9C94089, 0x7D7D87FA, - 0xFAFA15EF, 0x5959EBB2, 0x4747C98E, 0xF0F00BFB, 0xADADEC41, - 0xD4D467B3, 0xA2A2FD5F, 0xAFAFEA45, 0x9C9CBF23, 0xA4A4F753, - 0x727296E4, 0xC0C05B9B, 0xB7B7C275, 0xFDFD1CE1, 0x9393AE3D, - 0x26266A4C, 0x36365A6C, 0x3F3F417E, 0xF7F702F5, 0xCCCC4F83, - 0x34345C68, 0xA5A5F451, 0xE5E534D1, 0xF1F108F9, 0x717193E2, - 0xD8D873AB, 0x31315362, 0x15153F2A, 0x04040C08, 0xC7C75295, - 0x23236546, 0xC3C35E9D, 0x18182830, 0x9696A137, 0x05050F0A, - 0x9A9AB52F, 0x0707090E, 0x12123624, 0x80809B1B, 0xE2E23DDF, - 0xEBEB26CD, 0x2727694E, 0xB2B2CD7F, 0x75759FEA, 0x09091B12, - 0x83839E1D, 0x2C2C7458, 0x1A1A2E34, 0x1B1B2D36, 0x6E6EB2DC, - 0x5A5AEEB4, 0xA0A0FB5B, 0x5252F6A4, 0x3B3B4D76, 0xD6D661B7, - 0xB3B3CE7D, 0x29297B52, 0xE3E33EDD, 0x2F2F715E, 0x84849713, - 0x5353F5A6, 0xD1D168B9, 0x00000000, 0xEDED2CC1, 0x20206040, - 0xFCFC1FE3, 0xB1B1C879, 0x5B5BEDB6, 0x6A6ABED4, 0xCBCB468D, - 0xBEBED967, 0x39394B72, 0x4A4ADE94, 0x4C4CD498, 0x5858E8B0, - 0xCFCF4A85, 0xD0D06BBB, 0xEFEF2AC5, 0xAAAAE54F, 0xFBFB16ED, - 0x4343C586, 0x4D4DD79A, 0x33335566, 0x85859411, 0x4545CF8A, - 0xF9F910E9, 0x02020604, 0x7F7F81FE, 0x5050F0A0, 0x3C3C4478, - 0x9F9FBA25, 0xA8A8E34B, 0x5151F3A2, 0xA3A3FE5D, 0x4040C080, - 0x8F8F8A05, 0x9292AD3F, 0x9D9DBC21, 0x38384870, 0xF5F504F1, - 0xBCBCDF63, 0xB6B6C177, 0xDADA75AF, 0x21216342, 0x10103020, - 0xFFFF1AE5, 0xF3F30EFD, 0xD2D26DBF, 0xCDCD4C81, 0x0C0C1418, - 0x13133526, 0xECEC2FC3, 0x5F5FE1BE, 0x9797A235, 0x4444CC88, - 0x1717392E, 0xC4C45793, 0xA7A7F255, 0x7E7E82FC, 0x3D3D477A, - 0x6464ACC8, 0x5D5DE7BA, 0x19192B32, 0x737395E6, 0x6060A0C0, - 0x81819819, 0x4F4FD19E, 0xDCDC7FA3, 0x22226644, 0x2A2A7E54, - 0x9090AB3B, 0x8888830B, 0x4646CA8C, 0xEEEE29C7, 0xB8B8D36B, - 0x14143C28, 0xDEDE79A7, 0x5E5EE2BC, 0x0B0B1D16, 0xDBDB76AD, - 0xE0E03BDB, 0x32325664, 0x3A3A4E74, 0x0A0A1E14, 0x4949DB92, - 0x06060A0C, 0x24246C48, 0x5C5CE4B8, 0xC2C25D9F, 0xD3D36EBD, - 0xACACEF43, 0x6262A6C4, 0x9191A839, 0x9595A431, 0xE4E437D3, - 0x79798BF2, 0xE7E732D5, 0xC8C8438B, 0x3737596E, 0x6D6DB7DA, - 0x8D8D8C01, 0xD5D564B1, 0x4E4ED29C, 0xA9A9E049, 0x6C6CB4D8, - 0x5656FAAC, 0xF4F407F3, 0xEAEA25CF, 0x6565AFCA, 0x7A7A8EF4, - 0xAEAEE947, 0x08081810, 0xBABAD56F, 0x787888F0, 0x25256F4A, - 0x2E2E725C, 0x1C1C2438, 0xA6A6F157, 0xB4B4C773, 0xC6C65197, - 0xE8E823CB, 0xDDDD7CA1, 0x74749CE8, 0x1F1F213E, 0x4B4BDD96, - 0xBDBDDC61, 0x8B8B860D, 0x8A8A850F, 0x707090E0, 0x3E3E427C, - 0xB5B5C471, 0x6666AACC, 0x4848D890, 0x03030506, 0xF6F601F7, - 0x0E0E121C, 0x6161A3C2, 0x35355F6A, 0x5757F9AE, 0xB9B9D069, - 0x86869117, 0xC1C15899, 0x1D1D273A, 0x9E9EB927, 0xE1E138D9, - 0xF8F813EB, 0x9898B32B, 0x11113322, 0x6969BBD2, 0xD9D970A9, - 0x8E8E8907, 0x9494A733, 0x9B9BB62D, 0x1E1E223C, 0x87879215, - 0xE9E920C9, 0xCECE4987, 0x5555FFAA, 0x28287850, 0xDFDF7AA5, - 0x8C8C8F03, 0xA1A1F859, 0x89898009, 0x0D0D171A, 0xBFBFDA65, - 0xE6E631D7, 0x4242C684, 0x6868B8D0, 0x4141C382, 0x9999B029, - 0x2D2D775A, 0x0F0F111E, 0xB0B0CB7B, 0x5454FCA8, 0xBBBBD66D, - 0x16163A2C, - }; - - // Lookup table for row 0 inverse transforms, see section 5.2.1 of original - // spec. - private static final int[] TI0 = { - 0x51F4A750, 0x7E416553, 0x1A17A4C3, 0x3A275E96, 0x3BAB6BCB, - 0x1F9D45F1, 0xACFA58AB, 0x4BE30393, 0x2030FA55, 0xAD766DF6, - 0x88CC7691, 0xF5024C25, 0x4FE5D7FC, 0xC52ACBD7, 0x26354480, - 0xB562A38F, 0xDEB15A49, 0x25BA1B67, 0x45EA0E98, 0x5DFEC0E1, - 0xC32F7502, 0x814CF012, 0x8D4697A3, 0x6BD3F9C6, 0x038F5FE7, - 0x15929C95, 0xBF6D7AEB, 0x955259DA, 0xD4BE832D, 0x587421D3, - 0x49E06929, 0x8EC9C844, 0x75C2896A, 0xF48E7978, 0x99583E6B, - 0x27B971DD, 0xBEE14FB6, 0xF088AD17, 0xC920AC66, 0x7DCE3AB4, - 0x63DF4A18, 0xE51A3182, 0x97513360, 0x62537F45, 0xB16477E0, - 0xBB6BAE84, 0xFE81A01C, 0xF9082B94, 0x70486858, 0x8F45FD19, - 0x94DE6C87, 0x527BF8B7, 0xAB73D323, 0x724B02E2, 0xE31F8F57, - 0x6655AB2A, 0xB2EB2807, 0x2FB5C203, 0x86C57B9A, 0xD33708A5, - 0x302887F2, 0x23BFA5B2, 0x02036ABA, 0xED16825C, 0x8ACF1C2B, - 0xA779B492, 0xF307F2F0, 0x4E69E2A1, 0x65DAF4CD, 0x0605BED5, - 0xD134621F, 0xC4A6FE8A, 0x342E539D, 0xA2F355A0, 0x058AE132, - 0xA4F6EB75, 0x0B83EC39, 0x4060EFAA, 0x5E719F06, 0xBD6E1051, - 0x3E218AF9, 0x96DD063D, 0xDD3E05AE, 0x4DE6BD46, 0x91548DB5, - 0x71C45D05, 0x0406D46F, 0x605015FF, 0x1998FB24, 0xD6BDE997, - 0x894043CC, 0x67D99E77, 0xB0E842BD, 0x07898B88, 0xE7195B38, - 0x79C8EEDB, 0xA17C0A47, 0x7C420FE9, 0xF8841EC9, 0x00000000, - 0x09808683, 0x322BED48, 0x1E1170AC, 0x6C5A724E, 0xFD0EFFFB, - 0x0F853856, 0x3DAED51E, 0x362D3927, 0x0A0FD964, 0x685CA621, - 0x9B5B54D1, 0x24362E3A, 0x0C0A67B1, 0x9357E70F, 0xB4EE96D2, - 0x1B9B919E, 0x80C0C54F, 0x61DC20A2, 0x5A774B69, 0x1C121A16, - 0xE293BA0A, 0xC0A02AE5, 0x3C22E043, 0x121B171D, 0x0E090D0B, - 0xF28BC7AD, 0x2DB6A8B9, 0x141EA9C8, 0x57F11985, 0xAF75074C, - 0xEE99DDBB, 0xA37F60FD, 0xF701269F, 0x5C72F5BC, 0x44663BC5, - 0x5BFB7E34, 0x8B432976, 0xCB23C6DC, 0xB6EDFC68, 0xB8E4F163, - 0xD731DCCA, 0x42638510, 0x13972240, 0x84C61120, 0x854A247D, - 0xD2BB3DF8, 0xAEF93211, 0xC729A16D, 0x1D9E2F4B, 0xDCB230F3, - 0x0D8652EC, 0x77C1E3D0, 0x2BB3166C, 0xA970B999, 0x119448FA, - 0x47E96422, 0xA8FC8CC4, 0xA0F03F1A, 0x567D2CD8, 0x223390EF, - 0x87494EC7, 0xD938D1C1, 0x8CCAA2FE, 0x98D40B36, 0xA6F581CF, - 0xA57ADE28, 0xDAB78E26, 0x3FADBFA4, 0x2C3A9DE4, 0x5078920D, - 0x6A5FCC9B, 0x547E4662, 0xF68D13C2, 0x90D8B8E8, 0x2E39F75E, - 0x82C3AFF5, 0x9F5D80BE, 0x69D0937C, 0x6FD52DA9, 0xCF2512B3, - 0xC8AC993B, 0x10187DA7, 0xE89C636E, 0xDB3BBB7B, 0xCD267809, - 0x6E5918F4, 0xEC9AB701, 0x834F9AA8, 0xE6956E65, 0xAAFFE67E, - 0x21BCCF08, 0xEF15E8E6, 0xBAE79BD9, 0x4A6F36CE, 0xEA9F09D4, - 0x29B07CD6, 0x31A4B2AF, 0x2A3F2331, 0xC6A59430, 0x35A266C0, - 0x744EBC37, 0xFC82CAA6, 0xE090D0B0, 0x33A7D815, 0xF104984A, - 0x41ECDAF7, 0x7FCD500E, 0x1791F62F, 0x764DD68D, 0x43EFB04D, - 0xCCAA4D54, 0xE49604DF, 0x9ED1B5E3, 0x4C6A881B, 0xC12C1FB8, - 0x4665517F, 0x9D5EEA04, 0x018C355D, 0xFA877473, 0xFB0B412E, - 0xB3671D5A, 0x92DBD252, 0xE9105633, 0x6DD64713, 0x9AD7618C, - 0x37A10C7A, 0x59F8148E, 0xEB133C89, 0xCEA927EE, 0xB761C935, - 0xE11CE5ED, 0x7A47B13C, 0x9CD2DF59, 0x55F2733F, 0x1814CE79, - 0x73C737BF, 0x53F7CDEA, 0x5FFDAA5B, 0xDF3D6F14, 0x7844DB86, - 0xCAAFF381, 0xB968C43E, 0x3824342C, 0xC2A3405F, 0x161DC372, - 0xBCE2250C, 0x283C498B, 0xFF0D9541, 0x39A80171, 0x080CB3DE, - 0xD8B4E49C, 0x6456C190, 0x7BCB8461, 0xD532B670, 0x486C5C74, - 0xD0B85742, - }; - - // Lookup table for row 1 inverse transforms, see section 5.2.1 of original - // spec. - private static final int[] TI1 = { - 0x5051F4A7, 0x537E4165, 0xC31A17A4, 0x963A275E, 0xCB3BAB6B, - 0xF11F9D45, 0xABACFA58, 0x934BE303, 0x552030FA, 0xF6AD766D, - 0x9188CC76, 0x25F5024C, 0xFC4FE5D7, 0xD7C52ACB, 0x80263544, - 0x8FB562A3, 0x49DEB15A, 0x6725BA1B, 0x9845EA0E, 0xE15DFEC0, - 0x02C32F75, 0x12814CF0, 0xA38D4697, 0xC66BD3F9, 0xE7038F5F, - 0x9515929C, 0xEBBF6D7A, 0xDA955259, 0x2DD4BE83, 0xD3587421, - 0x2949E069, 0x448EC9C8, 0x6A75C289, 0x78F48E79, 0x6B99583E, - 0xDD27B971, 0xB6BEE14F, 0x17F088AD, 0x66C920AC, 0xB47DCE3A, - 0x1863DF4A, 0x82E51A31, 0x60975133, 0x4562537F, 0xE0B16477, - 0x84BB6BAE, 0x1CFE81A0, 0x94F9082B, 0x58704868, 0x198F45FD, - 0x8794DE6C, 0xB7527BF8, 0x23AB73D3, 0xE2724B02, 0x57E31F8F, - 0x2A6655AB, 0x07B2EB28, 0x032FB5C2, 0x9A86C57B, 0xA5D33708, - 0xF2302887, 0xB223BFA5, 0xBA02036A, 0x5CED1682, 0x2B8ACF1C, - 0x92A779B4, 0xF0F307F2, 0xA14E69E2, 0xCD65DAF4, 0xD50605BE, - 0x1FD13462, 0x8AC4A6FE, 0x9D342E53, 0xA0A2F355, 0x32058AE1, - 0x75A4F6EB, 0x390B83EC, 0xAA4060EF, 0x065E719F, 0x51BD6E10, - 0xF93E218A, 0x3D96DD06, 0xAEDD3E05, 0x464DE6BD, 0xB591548D, - 0x0571C45D, 0x6F0406D4, 0xFF605015, 0x241998FB, 0x97D6BDE9, - 0xCC894043, 0x7767D99E, 0xBDB0E842, 0x8807898B, 0x38E7195B, - 0xDB79C8EE, 0x47A17C0A, 0xE97C420F, 0xC9F8841E, 0x00000000, - 0x83098086, 0x48322BED, 0xAC1E1170, 0x4E6C5A72, 0xFBFD0EFF, - 0x560F8538, 0x1E3DAED5, 0x27362D39, 0x640A0FD9, 0x21685CA6, - 0xD19B5B54, 0x3A24362E, 0xB10C0A67, 0x0F9357E7, 0xD2B4EE96, - 0x9E1B9B91, 0x4F80C0C5, 0xA261DC20, 0x695A774B, 0x161C121A, - 0x0AE293BA, 0xE5C0A02A, 0x433C22E0, 0x1D121B17, 0x0B0E090D, - 0xADF28BC7, 0xB92DB6A8, 0xC8141EA9, 0x8557F119, 0x4CAF7507, - 0xBBEE99DD, 0xFDA37F60, 0x9FF70126, 0xBC5C72F5, 0xC544663B, - 0x345BFB7E, 0x768B4329, 0xDCCB23C6, 0x68B6EDFC, 0x63B8E4F1, - 0xCAD731DC, 0x10426385, 0x40139722, 0x2084C611, 0x7D854A24, - 0xF8D2BB3D, 0x11AEF932, 0x6DC729A1, 0x4B1D9E2F, 0xF3DCB230, - 0xEC0D8652, 0xD077C1E3, 0x6C2BB316, 0x99A970B9, 0xFA119448, - 0x2247E964, 0xC4A8FC8C, 0x1AA0F03F, 0xD8567D2C, 0xEF223390, - 0xC787494E, 0xC1D938D1, 0xFE8CCAA2, 0x3698D40B, 0xCFA6F581, - 0x28A57ADE, 0x26DAB78E, 0xA43FADBF, 0xE42C3A9D, 0x0D507892, - 0x9B6A5FCC, 0x62547E46, 0xC2F68D13, 0xE890D8B8, 0x5E2E39F7, - 0xF582C3AF, 0xBE9F5D80, 0x7C69D093, 0xA96FD52D, 0xB3CF2512, - 0x3BC8AC99, 0xA710187D, 0x6EE89C63, 0x7BDB3BBB, 0x09CD2678, - 0xF46E5918, 0x01EC9AB7, 0xA8834F9A, 0x65E6956E, 0x7EAAFFE6, - 0x0821BCCF, 0xE6EF15E8, 0xD9BAE79B, 0xCE4A6F36, 0xD4EA9F09, - 0xD629B07C, 0xAF31A4B2, 0x312A3F23, 0x30C6A594, 0xC035A266, - 0x37744EBC, 0xA6FC82CA, 0xB0E090D0, 0x1533A7D8, 0x4AF10498, - 0xF741ECDA, 0x0E7FCD50, 0x2F1791F6, 0x8D764DD6, 0x4D43EFB0, - 0x54CCAA4D, 0xDFE49604, 0xE39ED1B5, 0x1B4C6A88, 0xB8C12C1F, - 0x7F466551, 0x049D5EEA, 0x5D018C35, 0x73FA8774, 0x2EFB0B41, - 0x5AB3671D, 0x5292DBD2, 0x33E91056, 0x136DD647, 0x8C9AD761, - 0x7A37A10C, 0x8E59F814, 0x89EB133C, 0xEECEA927, 0x35B761C9, - 0xEDE11CE5, 0x3C7A47B1, 0x599CD2DF, 0x3F55F273, 0x791814CE, - 0xBF73C737, 0xEA53F7CD, 0x5B5FFDAA, 0x14DF3D6F, 0x867844DB, - 0x81CAAFF3, 0x3EB968C4, 0x2C382434, 0x5FC2A340, 0x72161DC3, - 0x0CBCE225, 0x8B283C49, 0x41FF0D95, 0x7139A801, 0xDE080CB3, - 0x9CD8B4E4, 0x906456C1, 0x617BCB84, 0x70D532B6, 0x74486C5C, - 0x42D0B857, - }; - - // Lookup table for row 2 inverse transforms, see section 5.2.1 of original - // spec. - private static final int[] TI2 = { - 0xA75051F4, 0x65537E41, 0xA4C31A17, 0x5E963A27, 0x6BCB3BAB, - 0x45F11F9D, 0x58ABACFA, 0x03934BE3, 0xFA552030, 0x6DF6AD76, - 0x769188CC, 0x4C25F502, 0xD7FC4FE5, 0xCBD7C52A, 0x44802635, - 0xA38FB562, 0x5A49DEB1, 0x1B6725BA, 0x0E9845EA, 0xC0E15DFE, - 0x7502C32F, 0xF012814C, 0x97A38D46, 0xF9C66BD3, 0x5FE7038F, - 0x9C951592, 0x7AEBBF6D, 0x59DA9552, 0x832DD4BE, 0x21D35874, - 0x692949E0, 0xC8448EC9, 0x896A75C2, 0x7978F48E, 0x3E6B9958, - 0x71DD27B9, 0x4FB6BEE1, 0xAD17F088, 0xAC66C920, 0x3AB47DCE, - 0x4A1863DF, 0x3182E51A, 0x33609751, 0x7F456253, 0x77E0B164, - 0xAE84BB6B, 0xA01CFE81, 0x2B94F908, 0x68587048, 0xFD198F45, - 0x6C8794DE, 0xF8B7527B, 0xD323AB73, 0x02E2724B, 0x8F57E31F, - 0xAB2A6655, 0x2807B2EB, 0xC2032FB5, 0x7B9A86C5, 0x08A5D337, - 0x87F23028, 0xA5B223BF, 0x6ABA0203, 0x825CED16, 0x1C2B8ACF, - 0xB492A779, 0xF2F0F307, 0xE2A14E69, 0xF4CD65DA, 0xBED50605, - 0x621FD134, 0xFE8AC4A6, 0x539D342E, 0x55A0A2F3, 0xE132058A, - 0xEB75A4F6, 0xEC390B83, 0xEFAA4060, 0x9F065E71, 0x1051BD6E, - 0x8AF93E21, 0x063D96DD, 0x05AEDD3E, 0xBD464DE6, 0x8DB59154, - 0x5D0571C4, 0xD46F0406, 0x15FF6050, 0xFB241998, 0xE997D6BD, - 0x43CC8940, 0x9E7767D9, 0x42BDB0E8, 0x8B880789, 0x5B38E719, - 0xEEDB79C8, 0x0A47A17C, 0x0FE97C42, 0x1EC9F884, 0x00000000, - 0x86830980, 0xED48322B, 0x70AC1E11, 0x724E6C5A, 0xFFFBFD0E, - 0x38560F85, 0xD51E3DAE, 0x3927362D, 0xD9640A0F, 0xA621685C, - 0x54D19B5B, 0x2E3A2436, 0x67B10C0A, 0xE70F9357, 0x96D2B4EE, - 0x919E1B9B, 0xC54F80C0, 0x20A261DC, 0x4B695A77, 0x1A161C12, - 0xBA0AE293, 0x2AE5C0A0, 0xE0433C22, 0x171D121B, 0x0D0B0E09, - 0xC7ADF28B, 0xA8B92DB6, 0xA9C8141E, 0x198557F1, 0x074CAF75, - 0xDDBBEE99, 0x60FDA37F, 0x269FF701, 0xF5BC5C72, 0x3BC54466, - 0x7E345BFB, 0x29768B43, 0xC6DCCB23, 0xFC68B6ED, 0xF163B8E4, - 0xDCCAD731, 0x85104263, 0x22401397, 0x112084C6, 0x247D854A, - 0x3DF8D2BB, 0x3211AEF9, 0xA16DC729, 0x2F4B1D9E, 0x30F3DCB2, - 0x52EC0D86, 0xE3D077C1, 0x166C2BB3, 0xB999A970, 0x48FA1194, - 0x642247E9, 0x8CC4A8FC, 0x3F1AA0F0, 0x2CD8567D, 0x90EF2233, - 0x4EC78749, 0xD1C1D938, 0xA2FE8CCA, 0x0B3698D4, 0x81CFA6F5, - 0xDE28A57A, 0x8E26DAB7, 0xBFA43FAD, 0x9DE42C3A, 0x920D5078, - 0xCC9B6A5F, 0x4662547E, 0x13C2F68D, 0xB8E890D8, 0xF75E2E39, - 0xAFF582C3, 0x80BE9F5D, 0x937C69D0, 0x2DA96FD5, 0x12B3CF25, - 0x993BC8AC, 0x7DA71018, 0x636EE89C, 0xBB7BDB3B, 0x7809CD26, - 0x18F46E59, 0xB701EC9A, 0x9AA8834F, 0x6E65E695, 0xE67EAAFF, - 0xCF0821BC, 0xE8E6EF15, 0x9BD9BAE7, 0x36CE4A6F, 0x09D4EA9F, - 0x7CD629B0, 0xB2AF31A4, 0x23312A3F, 0x9430C6A5, 0x66C035A2, - 0xBC37744E, 0xCAA6FC82, 0xD0B0E090, 0xD81533A7, 0x984AF104, - 0xDAF741EC, 0x500E7FCD, 0xF62F1791, 0xD68D764D, 0xB04D43EF, - 0x4D54CCAA, 0x04DFE496, 0xB5E39ED1, 0x881B4C6A, 0x1FB8C12C, - 0x517F4665, 0xEA049D5E, 0x355D018C, 0x7473FA87, 0x412EFB0B, - 0x1D5AB367, 0xD25292DB, 0x5633E910, 0x47136DD6, 0x618C9AD7, - 0x0C7A37A1, 0x148E59F8, 0x3C89EB13, 0x27EECEA9, 0xC935B761, - 0xE5EDE11C, 0xB13C7A47, 0xDF599CD2, 0x733F55F2, 0xCE791814, - 0x37BF73C7, 0xCDEA53F7, 0xAA5B5FFD, 0x6F14DF3D, 0xDB867844, - 0xF381CAAF, 0xC43EB968, 0x342C3824, 0x405FC2A3, 0xC372161D, - 0x250CBCE2, 0x498B283C, 0x9541FF0D, 0x017139A8, 0xB3DE080C, - 0xE49CD8B4, 0xC1906456, 0x84617BCB, 0xB670D532, 0x5C74486C, - 0x5742D0B8, - }; - - // Lookup table for row 3 inverse transforms, see section 5.2.1 of original - // spec. - private static final int[] TI3 = { - 0xF4A75051, 0x4165537E, 0x17A4C31A, 0x275E963A, 0xAB6BCB3B, - 0x9D45F11F, 0xFA58ABAC, 0xE303934B, 0x30FA5520, 0x766DF6AD, - 0xCC769188, 0x024C25F5, 0xE5D7FC4F, 0x2ACBD7C5, 0x35448026, - 0x62A38FB5, 0xB15A49DE, 0xBA1B6725, 0xEA0E9845, 0xFEC0E15D, - 0x2F7502C3, 0x4CF01281, 0x4697A38D, 0xD3F9C66B, 0x8F5FE703, - 0x929C9515, 0x6D7AEBBF, 0x5259DA95, 0xBE832DD4, 0x7421D358, - 0xE0692949, 0xC9C8448E, 0xC2896A75, 0x8E7978F4, 0x583E6B99, - 0xB971DD27, 0xE14FB6BE, 0x88AD17F0, 0x20AC66C9, 0xCE3AB47D, - 0xDF4A1863, 0x1A3182E5, 0x51336097, 0x537F4562, 0x6477E0B1, - 0x6BAE84BB, 0x81A01CFE, 0x082B94F9, 0x48685870, 0x45FD198F, - 0xDE6C8794, 0x7BF8B752, 0x73D323AB, 0x4B02E272, 0x1F8F57E3, - 0x55AB2A66, 0xEB2807B2, 0xB5C2032F, 0xC57B9A86, 0x3708A5D3, - 0x2887F230, 0xBFA5B223, 0x036ABA02, 0x16825CED, 0xCF1C2B8A, - 0x79B492A7, 0x07F2F0F3, 0x69E2A14E, 0xDAF4CD65, 0x05BED506, - 0x34621FD1, 0xA6FE8AC4, 0x2E539D34, 0xF355A0A2, 0x8AE13205, - 0xF6EB75A4, 0x83EC390B, 0x60EFAA40, 0x719F065E, 0x6E1051BD, - 0x218AF93E, 0xDD063D96, 0x3E05AEDD, 0xE6BD464D, 0x548DB591, - 0xC45D0571, 0x06D46F04, 0x5015FF60, 0x98FB2419, 0xBDE997D6, - 0x4043CC89, 0xD99E7767, 0xE842BDB0, 0x898B8807, 0x195B38E7, - 0xC8EEDB79, 0x7C0A47A1, 0x420FE97C, 0x841EC9F8, 0x00000000, - 0x80868309, 0x2BED4832, 0x1170AC1E, 0x5A724E6C, 0x0EFFFBFD, - 0x8538560F, 0xAED51E3D, 0x2D392736, 0x0FD9640A, 0x5CA62168, - 0x5B54D19B, 0x362E3A24, 0x0A67B10C, 0x57E70F93, 0xEE96D2B4, - 0x9B919E1B, 0xC0C54F80, 0xDC20A261, 0x774B695A, 0x121A161C, - 0x93BA0AE2, 0xA02AE5C0, 0x22E0433C, 0x1B171D12, 0x090D0B0E, - 0x8BC7ADF2, 0xB6A8B92D, 0x1EA9C814, 0xF1198557, 0x75074CAF, - 0x99DDBBEE, 0x7F60FDA3, 0x01269FF7, 0x72F5BC5C, 0x663BC544, - 0xFB7E345B, 0x4329768B, 0x23C6DCCB, 0xEDFC68B6, 0xE4F163B8, - 0x31DCCAD7, 0x63851042, 0x97224013, 0xC6112084, 0x4A247D85, - 0xBB3DF8D2, 0xF93211AE, 0x29A16DC7, 0x9E2F4B1D, 0xB230F3DC, - 0x8652EC0D, 0xC1E3D077, 0xB3166C2B, 0x70B999A9, 0x9448FA11, - 0xE9642247, 0xFC8CC4A8, 0xF03F1AA0, 0x7D2CD856, 0x3390EF22, - 0x494EC787, 0x38D1C1D9, 0xCAA2FE8C, 0xD40B3698, 0xF581CFA6, - 0x7ADE28A5, 0xB78E26DA, 0xADBFA43F, 0x3A9DE42C, 0x78920D50, - 0x5FCC9B6A, 0x7E466254, 0x8D13C2F6, 0xD8B8E890, 0x39F75E2E, - 0xC3AFF582, 0x5D80BE9F, 0xD0937C69, 0xD52DA96F, 0x2512B3CF, - 0xAC993BC8, 0x187DA710, 0x9C636EE8, 0x3BBB7BDB, 0x267809CD, - 0x5918F46E, 0x9AB701EC, 0x4F9AA883, 0x956E65E6, 0xFFE67EAA, - 0xBCCF0821, 0x15E8E6EF, 0xE79BD9BA, 0x6F36CE4A, 0x9F09D4EA, - 0xB07CD629, 0xA4B2AF31, 0x3F23312A, 0xA59430C6, 0xA266C035, - 0x4EBC3774, 0x82CAA6FC, 0x90D0B0E0, 0xA7D81533, 0x04984AF1, - 0xECDAF741, 0xCD500E7F, 0x91F62F17, 0x4DD68D76, 0xEFB04D43, - 0xAA4D54CC, 0x9604DFE4, 0xD1B5E39E, 0x6A881B4C, 0x2C1FB8C1, - 0x65517F46, 0x5EEA049D, 0x8C355D01, 0x877473FA, 0x0B412EFB, - 0x671D5AB3, 0xDBD25292, 0x105633E9, 0xD647136D, 0xD7618C9A, - 0xA10C7A37, 0xF8148E59, 0x133C89EB, 0xA927EECE, 0x61C935B7, - 0x1CE5EDE1, 0x47B13C7A, 0xD2DF599C, 0xF2733F55, 0x14CE7918, - 0xC737BF73, 0xF7CDEA53, 0xFDAA5B5F, 0x3D6F14DF, 0x44DB8678, - 0xAFF381CA, 0x68C43EB9, 0x24342C38, 0xA3405FC2, 0x1DC37216, - 0xE2250CBC, 0x3C498B28, 0x0D9541FF, 0xA8017139, 0x0CB3DE08, - 0xB4E49CD8, 0x56C19064, 0xCB84617B, 0x32B670D5, 0x6C5C7448, - 0xB85742D0, - }; - - // Lookup table for inverse substitution transform of last round as - // described in the international journal article referenced. - private static final int[] TI4 = { - 0x52525252, 0x09090909, 0x6A6A6A6A, 0xD5D5D5D5, 0x30303030, - 0x36363636, 0xA5A5A5A5, 0x38383838, 0xBFBFBFBF, 0x40404040, - 0xA3A3A3A3, 0x9E9E9E9E, 0x81818181, 0xF3F3F3F3, 0xD7D7D7D7, - 0xFBFBFBFB, 0x7C7C7C7C, 0xE3E3E3E3, 0x39393939, 0x82828282, - 0x9B9B9B9B, 0x2F2F2F2F, 0xFFFFFFFF, 0x87878787, 0x34343434, - 0x8E8E8E8E, 0x43434343, 0x44444444, 0xC4C4C4C4, 0xDEDEDEDE, - 0xE9E9E9E9, 0xCBCBCBCB, 0x54545454, 0x7B7B7B7B, 0x94949494, - 0x32323232, 0xA6A6A6A6, 0xC2C2C2C2, 0x23232323, 0x3D3D3D3D, - 0xEEEEEEEE, 0x4C4C4C4C, 0x95959595, 0x0B0B0B0B, 0x42424242, - 0xFAFAFAFA, 0xC3C3C3C3, 0x4E4E4E4E, 0x08080808, 0x2E2E2E2E, - 0xA1A1A1A1, 0x66666666, 0x28282828, 0xD9D9D9D9, 0x24242424, - 0xB2B2B2B2, 0x76767676, 0x5B5B5B5B, 0xA2A2A2A2, 0x49494949, - 0x6D6D6D6D, 0x8B8B8B8B, 0xD1D1D1D1, 0x25252525, 0x72727272, - 0xF8F8F8F8, 0xF6F6F6F6, 0x64646464, 0x86868686, 0x68686868, - 0x98989898, 0x16161616, 0xD4D4D4D4, 0xA4A4A4A4, 0x5C5C5C5C, - 0xCCCCCCCC, 0x5D5D5D5D, 0x65656565, 0xB6B6B6B6, 0x92929292, - 0x6C6C6C6C, 0x70707070, 0x48484848, 0x50505050, 0xFDFDFDFD, - 0xEDEDEDED, 0xB9B9B9B9, 0xDADADADA, 0x5E5E5E5E, 0x15151515, - 0x46464646, 0x57575757, 0xA7A7A7A7, 0x8D8D8D8D, 0x9D9D9D9D, - 0x84848484, 0x90909090, 0xD8D8D8D8, 0xABABABAB, 0x00000000, - 0x8C8C8C8C, 0xBCBCBCBC, 0xD3D3D3D3, 0x0A0A0A0A, 0xF7F7F7F7, - 0xE4E4E4E4, 0x58585858, 0x05050505, 0xB8B8B8B8, 0xB3B3B3B3, - 0x45454545, 0x06060606, 0xD0D0D0D0, 0x2C2C2C2C, 0x1E1E1E1E, - 0x8F8F8F8F, 0xCACACACA, 0x3F3F3F3F, 0x0F0F0F0F, 0x02020202, - 0xC1C1C1C1, 0xAFAFAFAF, 0xBDBDBDBD, 0x03030303, 0x01010101, - 0x13131313, 0x8A8A8A8A, 0x6B6B6B6B, 0x3A3A3A3A, 0x91919191, - 0x11111111, 0x41414141, 0x4F4F4F4F, 0x67676767, 0xDCDCDCDC, - 0xEAEAEAEA, 0x97979797, 0xF2F2F2F2, 0xCFCFCFCF, 0xCECECECE, - 0xF0F0F0F0, 0xB4B4B4B4, 0xE6E6E6E6, 0x73737373, 0x96969696, - 0xACACACAC, 0x74747474, 0x22222222, 0xE7E7E7E7, 0xADADADAD, - 0x35353535, 0x85858585, 0xE2E2E2E2, 0xF9F9F9F9, 0x37373737, - 0xE8E8E8E8, 0x1C1C1C1C, 0x75757575, 0xDFDFDFDF, 0x6E6E6E6E, - 0x47474747, 0xF1F1F1F1, 0x1A1A1A1A, 0x71717171, 0x1D1D1D1D, - 0x29292929, 0xC5C5C5C5, 0x89898989, 0x6F6F6F6F, 0xB7B7B7B7, - 0x62626262, 0x0E0E0E0E, 0xAAAAAAAA, 0x18181818, 0xBEBEBEBE, - 0x1B1B1B1B, 0xFCFCFCFC, 0x56565656, 0x3E3E3E3E, 0x4B4B4B4B, - 0xC6C6C6C6, 0xD2D2D2D2, 0x79797979, 0x20202020, 0x9A9A9A9A, - 0xDBDBDBDB, 0xC0C0C0C0, 0xFEFEFEFE, 0x78787878, 0xCDCDCDCD, - 0x5A5A5A5A, 0xF4F4F4F4, 0x1F1F1F1F, 0xDDDDDDDD, 0xA8A8A8A8, - 0x33333333, 0x88888888, 0x07070707, 0xC7C7C7C7, 0x31313131, - 0xB1B1B1B1, 0x12121212, 0x10101010, 0x59595959, 0x27272727, - 0x80808080, 0xECECECEC, 0x5F5F5F5F, 0x60606060, 0x51515151, - 0x7F7F7F7F, 0xA9A9A9A9, 0x19191919, 0xB5B5B5B5, 0x4A4A4A4A, - 0x0D0D0D0D, 0x2D2D2D2D, 0xE5E5E5E5, 0x7A7A7A7A, 0x9F9F9F9F, - 0x93939393, 0xC9C9C9C9, 0x9C9C9C9C, 0xEFEFEFEF, 0xA0A0A0A0, - 0xE0E0E0E0, 0x3B3B3B3B, 0x4D4D4D4D, 0xAEAEAEAE, 0x2A2A2A2A, - 0xF5F5F5F5, 0xB0B0B0B0, 0xC8C8C8C8, 0xEBEBEBEB, 0xBBBBBBBB, - 0x3C3C3C3C, 0x83838383, 0x53535353, 0x99999999, 0x61616161, - 0x17171717, 0x2B2B2B2B, 0x04040404, 0x7E7E7E7E, 0xBABABABA, - 0x77777777, 0xD6D6D6D6, 0x26262626, 0xE1E1E1E1, 0x69696969, - 0x14141414, 0x63636363, 0x55555555, 0x21212121, 0x0C0C0C0C, - 0x7D7D7D7D, - }; - - // Lookup table for row 0 of the inverse mix column transform. - private static final int[] TMI0 = { - 0x00000000, 0x0E090D0B, 0x1C121A16, 0x121B171D, 0x3824342C, - 0x362D3927, 0x24362E3A, 0x2A3F2331, 0x70486858, 0x7E416553, - 0x6C5A724E, 0x62537F45, 0x486C5C74, 0x4665517F, 0x547E4662, - 0x5A774B69, 0xE090D0B0, 0xEE99DDBB, 0xFC82CAA6, 0xF28BC7AD, - 0xD8B4E49C, 0xD6BDE997, 0xC4A6FE8A, 0xCAAFF381, 0x90D8B8E8, - 0x9ED1B5E3, 0x8CCAA2FE, 0x82C3AFF5, 0xA8FC8CC4, 0xA6F581CF, - 0xB4EE96D2, 0xBAE79BD9, 0xDB3BBB7B, 0xD532B670, 0xC729A16D, - 0xC920AC66, 0xE31F8F57, 0xED16825C, 0xFF0D9541, 0xF104984A, - 0xAB73D323, 0xA57ADE28, 0xB761C935, 0xB968C43E, 0x9357E70F, - 0x9D5EEA04, 0x8F45FD19, 0x814CF012, 0x3BAB6BCB, 0x35A266C0, - 0x27B971DD, 0x29B07CD6, 0x038F5FE7, 0x0D8652EC, 0x1F9D45F1, - 0x119448FA, 0x4BE30393, 0x45EA0E98, 0x57F11985, 0x59F8148E, - 0x73C737BF, 0x7DCE3AB4, 0x6FD52DA9, 0x61DC20A2, 0xAD766DF6, - 0xA37F60FD, 0xB16477E0, 0xBF6D7AEB, 0x955259DA, 0x9B5B54D1, - 0x894043CC, 0x87494EC7, 0xDD3E05AE, 0xD33708A5, 0xC12C1FB8, - 0xCF2512B3, 0xE51A3182, 0xEB133C89, 0xF9082B94, 0xF701269F, - 0x4DE6BD46, 0x43EFB04D, 0x51F4A750, 0x5FFDAA5B, 0x75C2896A, - 0x7BCB8461, 0x69D0937C, 0x67D99E77, 0x3DAED51E, 0x33A7D815, - 0x21BCCF08, 0x2FB5C203, 0x058AE132, 0x0B83EC39, 0x1998FB24, - 0x1791F62F, 0x764DD68D, 0x7844DB86, 0x6A5FCC9B, 0x6456C190, - 0x4E69E2A1, 0x4060EFAA, 0x527BF8B7, 0x5C72F5BC, 0x0605BED5, - 0x080CB3DE, 0x1A17A4C3, 0x141EA9C8, 0x3E218AF9, 0x302887F2, - 0x223390EF, 0x2C3A9DE4, 0x96DD063D, 0x98D40B36, 0x8ACF1C2B, - 0x84C61120, 0xAEF93211, 0xA0F03F1A, 0xB2EB2807, 0xBCE2250C, - 0xE6956E65, 0xE89C636E, 0xFA877473, 0xF48E7978, 0xDEB15A49, - 0xD0B85742, 0xC2A3405F, 0xCCAA4D54, 0x41ECDAF7, 0x4FE5D7FC, - 0x5DFEC0E1, 0x53F7CDEA, 0x79C8EEDB, 0x77C1E3D0, 0x65DAF4CD, - 0x6BD3F9C6, 0x31A4B2AF, 0x3FADBFA4, 0x2DB6A8B9, 0x23BFA5B2, - 0x09808683, 0x07898B88, 0x15929C95, 0x1B9B919E, 0xA17C0A47, - 0xAF75074C, 0xBD6E1051, 0xB3671D5A, 0x99583E6B, 0x97513360, - 0x854A247D, 0x8B432976, 0xD134621F, 0xDF3D6F14, 0xCD267809, - 0xC32F7502, 0xE9105633, 0xE7195B38, 0xF5024C25, 0xFB0B412E, - 0x9AD7618C, 0x94DE6C87, 0x86C57B9A, 0x88CC7691, 0xA2F355A0, - 0xACFA58AB, 0xBEE14FB6, 0xB0E842BD, 0xEA9F09D4, 0xE49604DF, - 0xF68D13C2, 0xF8841EC9, 0xD2BB3DF8, 0xDCB230F3, 0xCEA927EE, - 0xC0A02AE5, 0x7A47B13C, 0x744EBC37, 0x6655AB2A, 0x685CA621, - 0x42638510, 0x4C6A881B, 0x5E719F06, 0x5078920D, 0x0A0FD964, - 0x0406D46F, 0x161DC372, 0x1814CE79, 0x322BED48, 0x3C22E043, - 0x2E39F75E, 0x2030FA55, 0xEC9AB701, 0xE293BA0A, 0xF088AD17, - 0xFE81A01C, 0xD4BE832D, 0xDAB78E26, 0xC8AC993B, 0xC6A59430, - 0x9CD2DF59, 0x92DBD252, 0x80C0C54F, 0x8EC9C844, 0xA4F6EB75, - 0xAAFFE67E, 0xB8E4F163, 0xB6EDFC68, 0x0C0A67B1, 0x02036ABA, - 0x10187DA7, 0x1E1170AC, 0x342E539D, 0x3A275E96, 0x283C498B, - 0x26354480, 0x7C420FE9, 0x724B02E2, 0x605015FF, 0x6E5918F4, - 0x44663BC5, 0x4A6F36CE, 0x587421D3, 0x567D2CD8, 0x37A10C7A, - 0x39A80171, 0x2BB3166C, 0x25BA1B67, 0x0F853856, 0x018C355D, - 0x13972240, 0x1D9E2F4B, 0x47E96422, 0x49E06929, 0x5BFB7E34, - 0x55F2733F, 0x7FCD500E, 0x71C45D05, 0x63DF4A18, 0x6DD64713, - 0xD731DCCA, 0xD938D1C1, 0xCB23C6DC, 0xC52ACBD7, 0xEF15E8E6, - 0xE11CE5ED, 0xF307F2F0, 0xFD0EFFFB, 0xA779B492, 0xA970B999, - 0xBB6BAE84, 0xB562A38F, 0x9F5D80BE, 0x91548DB5, 0x834F9AA8, - 0x8D4697A3, - }; - - // Lookup table for row 1 of the inverse mix column transform. - private static final int[] TMI1 = { - 0x00000000, 0x0B0E090D, 0x161C121A, 0x1D121B17, 0x2C382434, - 0x27362D39, 0x3A24362E, 0x312A3F23, 0x58704868, 0x537E4165, - 0x4E6C5A72, 0x4562537F, 0x74486C5C, 0x7F466551, 0x62547E46, - 0x695A774B, 0xB0E090D0, 0xBBEE99DD, 0xA6FC82CA, 0xADF28BC7, - 0x9CD8B4E4, 0x97D6BDE9, 0x8AC4A6FE, 0x81CAAFF3, 0xE890D8B8, - 0xE39ED1B5, 0xFE8CCAA2, 0xF582C3AF, 0xC4A8FC8C, 0xCFA6F581, - 0xD2B4EE96, 0xD9BAE79B, 0x7BDB3BBB, 0x70D532B6, 0x6DC729A1, - 0x66C920AC, 0x57E31F8F, 0x5CED1682, 0x41FF0D95, 0x4AF10498, - 0x23AB73D3, 0x28A57ADE, 0x35B761C9, 0x3EB968C4, 0x0F9357E7, - 0x049D5EEA, 0x198F45FD, 0x12814CF0, 0xCB3BAB6B, 0xC035A266, - 0xDD27B971, 0xD629B07C, 0xE7038F5F, 0xEC0D8652, 0xF11F9D45, - 0xFA119448, 0x934BE303, 0x9845EA0E, 0x8557F119, 0x8E59F814, - 0xBF73C737, 0xB47DCE3A, 0xA96FD52D, 0xA261DC20, 0xF6AD766D, - 0xFDA37F60, 0xE0B16477, 0xEBBF6D7A, 0xDA955259, 0xD19B5B54, - 0xCC894043, 0xC787494E, 0xAEDD3E05, 0xA5D33708, 0xB8C12C1F, - 0xB3CF2512, 0x82E51A31, 0x89EB133C, 0x94F9082B, 0x9FF70126, - 0x464DE6BD, 0x4D43EFB0, 0x5051F4A7, 0x5B5FFDAA, 0x6A75C289, - 0x617BCB84, 0x7C69D093, 0x7767D99E, 0x1E3DAED5, 0x1533A7D8, - 0x0821BCCF, 0x032FB5C2, 0x32058AE1, 0x390B83EC, 0x241998FB, - 0x2F1791F6, 0x8D764DD6, 0x867844DB, 0x9B6A5FCC, 0x906456C1, - 0xA14E69E2, 0xAA4060EF, 0xB7527BF8, 0xBC5C72F5, 0xD50605BE, - 0xDE080CB3, 0xC31A17A4, 0xC8141EA9, 0xF93E218A, 0xF2302887, - 0xEF223390, 0xE42C3A9D, 0x3D96DD06, 0x3698D40B, 0x2B8ACF1C, - 0x2084C611, 0x11AEF932, 0x1AA0F03F, 0x07B2EB28, 0x0CBCE225, - 0x65E6956E, 0x6EE89C63, 0x73FA8774, 0x78F48E79, 0x49DEB15A, - 0x42D0B857, 0x5FC2A340, 0x54CCAA4D, 0xF741ECDA, 0xFC4FE5D7, - 0xE15DFEC0, 0xEA53F7CD, 0xDB79C8EE, 0xD077C1E3, 0xCD65DAF4, - 0xC66BD3F9, 0xAF31A4B2, 0xA43FADBF, 0xB92DB6A8, 0xB223BFA5, - 0x83098086, 0x8807898B, 0x9515929C, 0x9E1B9B91, 0x47A17C0A, - 0x4CAF7507, 0x51BD6E10, 0x5AB3671D, 0x6B99583E, 0x60975133, - 0x7D854A24, 0x768B4329, 0x1FD13462, 0x14DF3D6F, 0x09CD2678, - 0x02C32F75, 0x33E91056, 0x38E7195B, 0x25F5024C, 0x2EFB0B41, - 0x8C9AD761, 0x8794DE6C, 0x9A86C57B, 0x9188CC76, 0xA0A2F355, - 0xABACFA58, 0xB6BEE14F, 0xBDB0E842, 0xD4EA9F09, 0xDFE49604, - 0xC2F68D13, 0xC9F8841E, 0xF8D2BB3D, 0xF3DCB230, 0xEECEA927, - 0xE5C0A02A, 0x3C7A47B1, 0x37744EBC, 0x2A6655AB, 0x21685CA6, - 0x10426385, 0x1B4C6A88, 0x065E719F, 0x0D507892, 0x640A0FD9, - 0x6F0406D4, 0x72161DC3, 0x791814CE, 0x48322BED, 0x433C22E0, - 0x5E2E39F7, 0x552030FA, 0x01EC9AB7, 0x0AE293BA, 0x17F088AD, - 0x1CFE81A0, 0x2DD4BE83, 0x26DAB78E, 0x3BC8AC99, 0x30C6A594, - 0x599CD2DF, 0x5292DBD2, 0x4F80C0C5, 0x448EC9C8, 0x75A4F6EB, - 0x7EAAFFE6, 0x63B8E4F1, 0x68B6EDFC, 0xB10C0A67, 0xBA02036A, - 0xA710187D, 0xAC1E1170, 0x9D342E53, 0x963A275E, 0x8B283C49, - 0x80263544, 0xE97C420F, 0xE2724B02, 0xFF605015, 0xF46E5918, - 0xC544663B, 0xCE4A6F36, 0xD3587421, 0xD8567D2C, 0x7A37A10C, - 0x7139A801, 0x6C2BB316, 0x6725BA1B, 0x560F8538, 0x5D018C35, - 0x40139722, 0x4B1D9E2F, 0x2247E964, 0x2949E069, 0x345BFB7E, - 0x3F55F273, 0x0E7FCD50, 0x0571C45D, 0x1863DF4A, 0x136DD647, - 0xCAD731DC, 0xC1D938D1, 0xDCCB23C6, 0xD7C52ACB, 0xE6EF15E8, - 0xEDE11CE5, 0xF0F307F2, 0xFBFD0EFF, 0x92A779B4, 0x99A970B9, - 0x84BB6BAE, 0x8FB562A3, 0xBE9F5D80, 0xB591548D, 0xA8834F9A, - 0xA38D4697, - }; - - // Lookup table for row 2 of the inverse mix column transform. - private static final int[] TMI2 = { - 0x00000000, 0x0D0B0E09, 0x1A161C12, 0x171D121B, 0x342C3824, - 0x3927362D, 0x2E3A2436, 0x23312A3F, 0x68587048, 0x65537E41, - 0x724E6C5A, 0x7F456253, 0x5C74486C, 0x517F4665, 0x4662547E, - 0x4B695A77, 0xD0B0E090, 0xDDBBEE99, 0xCAA6FC82, 0xC7ADF28B, - 0xE49CD8B4, 0xE997D6BD, 0xFE8AC4A6, 0xF381CAAF, 0xB8E890D8, - 0xB5E39ED1, 0xA2FE8CCA, 0xAFF582C3, 0x8CC4A8FC, 0x81CFA6F5, - 0x96D2B4EE, 0x9BD9BAE7, 0xBB7BDB3B, 0xB670D532, 0xA16DC729, - 0xAC66C920, 0x8F57E31F, 0x825CED16, 0x9541FF0D, 0x984AF104, - 0xD323AB73, 0xDE28A57A, 0xC935B761, 0xC43EB968, 0xE70F9357, - 0xEA049D5E, 0xFD198F45, 0xF012814C, 0x6BCB3BAB, 0x66C035A2, - 0x71DD27B9, 0x7CD629B0, 0x5FE7038F, 0x52EC0D86, 0x45F11F9D, - 0x48FA1194, 0x03934BE3, 0x0E9845EA, 0x198557F1, 0x148E59F8, - 0x37BF73C7, 0x3AB47DCE, 0x2DA96FD5, 0x20A261DC, 0x6DF6AD76, - 0x60FDA37F, 0x77E0B164, 0x7AEBBF6D, 0x59DA9552, 0x54D19B5B, - 0x43CC8940, 0x4EC78749, 0x05AEDD3E, 0x08A5D337, 0x1FB8C12C, - 0x12B3CF25, 0x3182E51A, 0x3C89EB13, 0x2B94F908, 0x269FF701, - 0xBD464DE6, 0xB04D43EF, 0xA75051F4, 0xAA5B5FFD, 0x896A75C2, - 0x84617BCB, 0x937C69D0, 0x9E7767D9, 0xD51E3DAE, 0xD81533A7, - 0xCF0821BC, 0xC2032FB5, 0xE132058A, 0xEC390B83, 0xFB241998, - 0xF62F1791, 0xD68D764D, 0xDB867844, 0xCC9B6A5F, 0xC1906456, - 0xE2A14E69, 0xEFAA4060, 0xF8B7527B, 0xF5BC5C72, 0xBED50605, - 0xB3DE080C, 0xA4C31A17, 0xA9C8141E, 0x8AF93E21, 0x87F23028, - 0x90EF2233, 0x9DE42C3A, 0x063D96DD, 0x0B3698D4, 0x1C2B8ACF, - 0x112084C6, 0x3211AEF9, 0x3F1AA0F0, 0x2807B2EB, 0x250CBCE2, - 0x6E65E695, 0x636EE89C, 0x7473FA87, 0x7978F48E, 0x5A49DEB1, - 0x5742D0B8, 0x405FC2A3, 0x4D54CCAA, 0xDAF741EC, 0xD7FC4FE5, - 0xC0E15DFE, 0xCDEA53F7, 0xEEDB79C8, 0xE3D077C1, 0xF4CD65DA, - 0xF9C66BD3, 0xB2AF31A4, 0xBFA43FAD, 0xA8B92DB6, 0xA5B223BF, - 0x86830980, 0x8B880789, 0x9C951592, 0x919E1B9B, 0x0A47A17C, - 0x074CAF75, 0x1051BD6E, 0x1D5AB367, 0x3E6B9958, 0x33609751, - 0x247D854A, 0x29768B43, 0x621FD134, 0x6F14DF3D, 0x7809CD26, - 0x7502C32F, 0x5633E910, 0x5B38E719, 0x4C25F502, 0x412EFB0B, - 0x618C9AD7, 0x6C8794DE, 0x7B9A86C5, 0x769188CC, 0x55A0A2F3, - 0x58ABACFA, 0x4FB6BEE1, 0x42BDB0E8, 0x09D4EA9F, 0x04DFE496, - 0x13C2F68D, 0x1EC9F884, 0x3DF8D2BB, 0x30F3DCB2, 0x27EECEA9, - 0x2AE5C0A0, 0xB13C7A47, 0xBC37744E, 0xAB2A6655, 0xA621685C, - 0x85104263, 0x881B4C6A, 0x9F065E71, 0x920D5078, 0xD9640A0F, - 0xD46F0406, 0xC372161D, 0xCE791814, 0xED48322B, 0xE0433C22, - 0xF75E2E39, 0xFA552030, 0xB701EC9A, 0xBA0AE293, 0xAD17F088, - 0xA01CFE81, 0x832DD4BE, 0x8E26DAB7, 0x993BC8AC, 0x9430C6A5, - 0xDF599CD2, 0xD25292DB, 0xC54F80C0, 0xC8448EC9, 0xEB75A4F6, - 0xE67EAAFF, 0xF163B8E4, 0xFC68B6ED, 0x67B10C0A, 0x6ABA0203, - 0x7DA71018, 0x70AC1E11, 0x539D342E, 0x5E963A27, 0x498B283C, - 0x44802635, 0x0FE97C42, 0x02E2724B, 0x15FF6050, 0x18F46E59, - 0x3BC54466, 0x36CE4A6F, 0x21D35874, 0x2CD8567D, 0x0C7A37A1, - 0x017139A8, 0x166C2BB3, 0x1B6725BA, 0x38560F85, 0x355D018C, - 0x22401397, 0x2F4B1D9E, 0x642247E9, 0x692949E0, 0x7E345BFB, - 0x733F55F2, 0x500E7FCD, 0x5D0571C4, 0x4A1863DF, 0x47136DD6, - 0xDCCAD731, 0xD1C1D938, 0xC6DCCB23, 0xCBD7C52A, 0xE8E6EF15, - 0xE5EDE11C, 0xF2F0F307, 0xFFFBFD0E, 0xB492A779, 0xB999A970, - 0xAE84BB6B, 0xA38FB562, 0x80BE9F5D, 0x8DB59154, 0x9AA8834F, - 0x97A38D46, - }; - - // Lookup table for row 3 of the inverse mix column transform. - private static final int[] TMI3 = { - 0x00000000, 0x090D0B0E, 0x121A161C, 0x1B171D12, 0x24342C38, - 0x2D392736, 0x362E3A24, 0x3F23312A, 0x48685870, 0x4165537E, - 0x5A724E6C, 0x537F4562, 0x6C5C7448, 0x65517F46, 0x7E466254, - 0x774B695A, 0x90D0B0E0, 0x99DDBBEE, 0x82CAA6FC, 0x8BC7ADF2, - 0xB4E49CD8, 0xBDE997D6, 0xA6FE8AC4, 0xAFF381CA, 0xD8B8E890, - 0xD1B5E39E, 0xCAA2FE8C, 0xC3AFF582, 0xFC8CC4A8, 0xF581CFA6, - 0xEE96D2B4, 0xE79BD9BA, 0x3BBB7BDB, 0x32B670D5, 0x29A16DC7, - 0x20AC66C9, 0x1F8F57E3, 0x16825CED, 0x0D9541FF, 0x04984AF1, - 0x73D323AB, 0x7ADE28A5, 0x61C935B7, 0x68C43EB9, 0x57E70F93, - 0x5EEA049D, 0x45FD198F, 0x4CF01281, 0xAB6BCB3B, 0xA266C035, - 0xB971DD27, 0xB07CD629, 0x8F5FE703, 0x8652EC0D, 0x9D45F11F, - 0x9448FA11, 0xE303934B, 0xEA0E9845, 0xF1198557, 0xF8148E59, - 0xC737BF73, 0xCE3AB47D, 0xD52DA96F, 0xDC20A261, 0x766DF6AD, - 0x7F60FDA3, 0x6477E0B1, 0x6D7AEBBF, 0x5259DA95, 0x5B54D19B, - 0x4043CC89, 0x494EC787, 0x3E05AEDD, 0x3708A5D3, 0x2C1FB8C1, - 0x2512B3CF, 0x1A3182E5, 0x133C89EB, 0x082B94F9, 0x01269FF7, - 0xE6BD464D, 0xEFB04D43, 0xF4A75051, 0xFDAA5B5F, 0xC2896A75, - 0xCB84617B, 0xD0937C69, 0xD99E7767, 0xAED51E3D, 0xA7D81533, - 0xBCCF0821, 0xB5C2032F, 0x8AE13205, 0x83EC390B, 0x98FB2419, - 0x91F62F17, 0x4DD68D76, 0x44DB8678, 0x5FCC9B6A, 0x56C19064, - 0x69E2A14E, 0x60EFAA40, 0x7BF8B752, 0x72F5BC5C, 0x05BED506, - 0x0CB3DE08, 0x17A4C31A, 0x1EA9C814, 0x218AF93E, 0x2887F230, - 0x3390EF22, 0x3A9DE42C, 0xDD063D96, 0xD40B3698, 0xCF1C2B8A, - 0xC6112084, 0xF93211AE, 0xF03F1AA0, 0xEB2807B2, 0xE2250CBC, - 0x956E65E6, 0x9C636EE8, 0x877473FA, 0x8E7978F4, 0xB15A49DE, - 0xB85742D0, 0xA3405FC2, 0xAA4D54CC, 0xECDAF741, 0xE5D7FC4F, - 0xFEC0E15D, 0xF7CDEA53, 0xC8EEDB79, 0xC1E3D077, 0xDAF4CD65, - 0xD3F9C66B, 0xA4B2AF31, 0xADBFA43F, 0xB6A8B92D, 0xBFA5B223, - 0x80868309, 0x898B8807, 0x929C9515, 0x9B919E1B, 0x7C0A47A1, - 0x75074CAF, 0x6E1051BD, 0x671D5AB3, 0x583E6B99, 0x51336097, - 0x4A247D85, 0x4329768B, 0x34621FD1, 0x3D6F14DF, 0x267809CD, - 0x2F7502C3, 0x105633E9, 0x195B38E7, 0x024C25F5, 0x0B412EFB, - 0xD7618C9A, 0xDE6C8794, 0xC57B9A86, 0xCC769188, 0xF355A0A2, - 0xFA58ABAC, 0xE14FB6BE, 0xE842BDB0, 0x9F09D4EA, 0x9604DFE4, - 0x8D13C2F6, 0x841EC9F8, 0xBB3DF8D2, 0xB230F3DC, 0xA927EECE, - 0xA02AE5C0, 0x47B13C7A, 0x4EBC3774, 0x55AB2A66, 0x5CA62168, - 0x63851042, 0x6A881B4C, 0x719F065E, 0x78920D50, 0x0FD9640A, - 0x06D46F04, 0x1DC37216, 0x14CE7918, 0x2BED4832, 0x22E0433C, - 0x39F75E2E, 0x30FA5520, 0x9AB701EC, 0x93BA0AE2, 0x88AD17F0, - 0x81A01CFE, 0xBE832DD4, 0xB78E26DA, 0xAC993BC8, 0xA59430C6, - 0xD2DF599C, 0xDBD25292, 0xC0C54F80, 0xC9C8448E, 0xF6EB75A4, - 0xFFE67EAA, 0xE4F163B8, 0xEDFC68B6, 0x0A67B10C, 0x036ABA02, - 0x187DA710, 0x1170AC1E, 0x2E539D34, 0x275E963A, 0x3C498B28, - 0x35448026, 0x420FE97C, 0x4B02E272, 0x5015FF60, 0x5918F46E, - 0x663BC544, 0x6F36CE4A, 0x7421D358, 0x7D2CD856, 0xA10C7A37, - 0xA8017139, 0xB3166C2B, 0xBA1B6725, 0x8538560F, 0x8C355D01, - 0x97224013, 0x9E2F4B1D, 0xE9642247, 0xE0692949, 0xFB7E345B, - 0xF2733F55, 0xCD500E7F, 0xC45D0571, 0xDF4A1863, 0xD647136D, - 0x31DCCAD7, 0x38D1C1D9, 0x23C6DCCB, 0x2ACBD7C5, 0x15E8E6EF, - 0x1CE5EDE1, 0x07F2F0F3, 0x0EFFFBFD, 0x79B492A7, 0x70B999A9, - 0x6BAE84BB, 0x62A38FB5, 0x5D80BE9F, 0x548DB591, 0x4F9AA883, - 0x4697A38D, - }; - - /** - * Return the block cipher size. - * - * @return the AES block cipher size (in bytes). - */ - int getBlockSize() { - return AESConstants.AES_BLOCK_SIZE; - } - - /** - * Verifies if the length argument is a valid key size or not. - * - * @param len the size of the key (in bytes) to be validated. - * - * @return {@code true} if the size of the key is valid else {@code false}. - */ - static boolean isKeySizeValid(int len) { - for (int kLength : AESConstants.AES_KEYSIZES) { - if (len == kLength) { - return true; - } - } - return false; - } - - /** - * Check algorithm and initalize round keys for decryption and encryption. - * - * @param decrypting [in] indicates if encrypting ({@code false}) or - * decrypting ({@code true}). - * @param algorithm [in] the case insentive string name for the AES cipher. - * @param key [in] the symmetric key byte array for encryption/decryption. - * - * @throws InvalidKeyException if an incorrect algorithm is given or if - * an invalid key size is provided. - */ - void init(boolean decrypting, String algorithm, byte[] key) - throws InvalidKeyException { - int decrypt = decrypting ? 1 : 0; - - if (!algorithm.equalsIgnoreCase("AES") - && !algorithm.equalsIgnoreCase("Rijndael")) { - throw new InvalidKeyException ("Invalid algorithm name."); - } - if (key.length == AESConstants.AES_KEYSIZES[0]) { - rounds = AES_128_ROUNDS; - } else if (key.length == AESConstants.AES_KEYSIZES[1]) { - rounds = AES_192_ROUNDS; - } else if (key.length == AESConstants.AES_KEYSIZES[2]) { - rounds = AES_256_ROUNDS; - } else { - throw new InvalidKeyException("Invalid key length (" + key.length - + ")."); - } - if (!MessageDigest.isEqual(prevKey, key)) { - if (sessionK == null) { - sessionK = new int[2][]; - } else { - Arrays.fill(sessionK[0], 0); - Arrays.fill(sessionK[1], 0); - } - sessionK[0] = genRoundKeys(key, rounds); - sessionK[1] = genInvRoundKeys(sessionK[0], rounds); - if (prevKey != null) { - Arrays.fill(prevKey, (byte) 0); - } - prevKey = key.clone(); - } - K = sessionK[decrypt]; - } - - /** - * Generate the cipher's round keys as outlined in section 5.2 of the spec. - * - * @param key [in] the symmetric key byte array. - * - * @return w the cipher round keys. - */ - private static int[] genRoundKeys(byte[] key, int rounds) { - int wLen = WB * (rounds + 1); - int[] w = new int[wLen]; - int nk = key.length / BW; - - for (int i = 0, j = 0; i < nk; i++, j += BW) { - w[i] = ((key[j] & 0xFF) << 24) | ((key[j + 1] & 0xFF) << 16) - | ((key[j + 2] & 0xFF) << 8) | (key[j + 3] & 0xFF); - } - for (int i = nk; i < wLen; i++) { - int tmp = w[i - 1]; - if (i % nk == 0) { - int rW = (tmp << 8) & 0xFFFFFF00 | (tmp >>> 24); - tmp = subWord(rW) ^ RCON[(i / nk) - 1]; - } else if ((nk > 6) && ((i % nk) == WB)) { - tmp = subWord(tmp); - } - w[i] = w[i - nk] ^ tmp; - } - - return w; - } - - /** - * Generate the inverse cipher round keys. - * - * @return w1 the inverse cipher round keys. - */ - private static int[] genInvRoundKeys(int[] w, int rounds) { - int kLen = w.length;; - int[] temp = new int[WB]; - int[] dw = new int[kLen]; - - // Intrinsics requires the inverse key expansion to be reverse order - // except for the first and last round key as the first two round keys - // are without a mix column transform. - for (int i = 1; i < rounds; i++) { - System.arraycopy(w, i * WB, temp, 0, WB); - temp[0] = TMI0[temp[0] >>> 24] ^ TMI1[(temp[0] >> 16) & 0xFF] - ^ TMI2[(temp[0] >> 8) & 0xFF] ^ TMI3[temp[0] & 0xFF]; - temp[1] = TMI0[temp[1] >>> 24] ^ TMI1[(temp[1] >> 16) & 0xFF] - ^ TMI2[(temp[1] >> 8) & 0xFF] ^ TMI3[temp[1] & 0xFF]; - temp[2] = TMI0[temp[2] >>> 24] ^ TMI1[(temp[2] >> 16) & 0xFF] - ^ TMI2[(temp[2] >> 8) & 0xFF] ^ TMI3[temp[2] & 0xFF]; - temp[3] = TMI0[temp[3] >>> 24] ^ TMI1[(temp[3] >> 16) & 0xFF] - ^ TMI2[(temp[3] >> 8) & 0xFF] ^ TMI3[temp[3] & 0xFF]; - System.arraycopy(temp, 0, dw, kLen - (i * WB), WB); - } - System.arraycopy(w, kLen - WB, dw, WB, WB); - System.arraycopy(w, 0, dw, 0, WB); - Arrays.fill(temp, 0); - - return dw; - } - - /** - * Subtitute the word as a step of key expansion. - * - * @param state [in] the targeted word for substituion. - * @param sub [in] the substitute table for cipher and inverse cipher. - * - * @return the substituted word. - */ - private static int subWord(int word) { - byte b0 = (byte) (word >>> 24); - byte b1 = (byte) ((word >> 16) & 0xFF); - byte b2 = (byte) ((word >> 8) & 0xFF); - byte b3 = (byte) (word & 0xFF); - - return ((SBOX[(b0 & 0xF0) >> 4][b0 & 0x0F] & 0xFF) << 24) - | ((SBOX[(b1 & 0xF0) >> 4][b1 & 0x0F] & 0xFF) << 16) - | ((SBOX[(b2 & 0xF0) >> 4][b2 & 0x0F] & 0xFF) << 8) - | (SBOX[(b3 & 0xF0) >> 4][b3 & 0x0F] & 0xFF); - } - - /** - * Method for one block of encryption. - * - * @param p [in] the plaintext to be encrypted. - * @param po [in] the plaintext offset in the array of bytes. - * @param c [out] the ciphertext output. - * @param co [in] the ciphertext offset in the array of bytes. - */ - @IntrinsicCandidate - private void implEncryptBlock(byte[] p, int po, byte[] c, int co) { - int ti0, ti1, ti2, ti3; - int a0, a1, a2, a3; - int w = K.length - WB; - - a0 = ((p[po] & 0xFF) << 24) ^ ((p[po + 1] & 0xFF) << 16) - ^ ((p[po + 2] & 0xFF) << 8) ^ (p[po + 3] & 0xFF) ^ K[0]; - a1 = ((p[po + 4] & 0xFF) << 24) ^ ((p[po + 5] & 0xFF) << 16) - ^ ((p[po + 6] & 0xFF) << 8) ^ (p[po + 7] & 0xFF) ^ K[1]; - a2 = ((p[po + 8] & 0xFF) << 24) ^ ((p[po + 9] & 0xFF) << 16) - ^ ((p[po + 10] & 0xFF) << 8) ^ (p[po + 11] & 0xFF) ^ K[2]; - a3 = ((p[po + 12] & 0xFF) << 24) ^ ((p[po + 13] & 0xFF) << 16) - ^ ((p[po + 14] & 0xFF) << 8) ^ (p[po + 15] & 0xFF) ^ K[3]; - - ti0 = T0[a0 >>> 24] ^ T1[(a1 >> 16) & 0xFF] - ^ T2[(a2 >> 8) & 0xFF] ^ T3[a3 & 0xFF] ^ K[4]; - ti1 = T0[a1 >>> 24] ^ T1[(a2 >> 16) & 0xFF] - ^ T2[(a3 >> 8) & 0xFF] ^ T3[a0 & 0xFF] ^ K[5]; - ti2 = T0[a2 >>> 24] ^ T1[(a3 >> 16) & 0xFF] - ^ T2[(a0 >> 8) & 0xFF] ^ T3[a1 & 0xFF] ^ K[6]; - ti3 = T0[a3 >>> 24] ^ T1[(a0 >> 16) & 0xFF] - ^ T2[(a1 >> 8) & 0xFF] ^ T3[a2 & 0xFF] ^ K[7]; - - a0 = T0[ti0 >>> 24] ^ T1[(ti1 >> 16) & 0xFF] - ^ T2[(ti2 >> 8) & 0xFF] ^ T3[ti3 & 0xFF] ^ K[8]; - a1 = T0[ti1 >>> 24] ^ T1[(ti2 >> 16) & 0xFF] - ^ T2[(ti3 >> 8) & 0xFF] ^ T3[ti0 & 0xFF] ^ K[9]; - a2 = T0[ti2 >>> 24] ^ T1[(ti3 >> 16) & 0xFF] - ^ T2[(ti0 >> 8) & 0xFF] ^ T3[ti1 & 0xFF] ^ K[10]; - a3 = T0[ti3 >>> 24] ^ T1[(ti0 >> 16) & 0xFF] - ^ T2[(ti1 >> 8) & 0xFF] ^ T3[ti2 & 0xFF] ^ K[11]; - - ti0 = T0[a0 >>> 24] ^ T1[(a1 >> 16) & 0xFF] - ^ T2[(a2 >> 8) & 0xFF] ^ T3[a3 & 0xFF] ^ K[12]; - ti1 = T0[a1 >>> 24] ^ T1[(a2 >> 16) & 0xFF] - ^ T2[(a3 >> 8) & 0xFF] ^ T3[a0 & 0xFF] ^ K[13]; - ti2 = T0[a2 >>> 24] ^ T1[(a3 >> 16) & 0xFF] - ^ T2[(a0 >> 8) & 0xFF] ^ T3[a1 & 0xFF] ^ K[14]; - ti3 = T0[a3 >>> 24] ^ T1[(a0 >> 16) & 0xFF] - ^ T2[(a1 >> 8) & 0xFF] ^ T3[a2 & 0xFF] ^ K[15]; - - a0 = T0[ti0 >>> 24] ^ T1[(ti1 >> 16) & 0xFF] - ^ T2[(ti2 >> 8) & 0xFF] ^ T3[ti3 & 0xFF] ^ K[16]; - a1 = T0[ti1 >>> 24] ^ T1[(ti2 >> 16) & 0xFF] - ^ T2[(ti3 >> 8) & 0xFF] ^ T3[ti0 & 0xFF] ^ K[17]; - a2 = T0[ti2 >>> 24] ^ T1[(ti3 >> 16) & 0xFF] - ^ T2[(ti0 >> 8) & 0xFF] ^ T3[ti1 & 0xFF] ^ K[18]; - a3 = T0[ti3 >>> 24] ^ T1[(ti0 >> 16) & 0xFF] - ^ T2[(ti1 >> 8) & 0xFF] ^ T3[ti2 & 0xFF] ^ K[19]; - - ti0 = T0[a0 >>> 24] ^ T1[(a1 >> 16) & 0xFF] - ^ T2[(a2 >> 8) & 0xFF] ^ T3[a3 & 0xFF] ^ K[20]; - ti1 = T0[a1 >>> 24] ^ T1[(a2 >> 16) & 0xFF] - ^ T2[(a3 >> 8) & 0xFF] ^ T3[a0 & 0xFF] ^ K[21]; - ti2 = T0[a2 >>> 24] ^ T1[(a3 >> 16) & 0xFF] - ^ T2[(a0 >> 8) & 0xFF] ^ T3[a1 & 0xFF] ^ K[22]; - ti3 = T0[a3 >>> 24] ^ T1[(a0 >> 16) & 0xFF] - ^ T2[(a1 >> 8) & 0xFF] ^ T3[a2 & 0xFF] ^ K[23]; - - a0 = T0[ti0 >>> 24] ^ T1[(ti1 >> 16) & 0xFF] - ^ T2[(ti2 >> 8) & 0xFF] ^ T3[ti3 & 0xFF] ^ K[24]; - a1 = T0[ti1 >>> 24] ^ T1[(ti2 >> 16) & 0xFF] - ^ T2[(ti3 >> 8) & 0xFF] ^ T3[ti0 & 0xFF] ^ K[25]; - a2 = T0[ti2 >>> 24] ^ T1[(ti3 >> 16) & 0xFF] - ^ T2[(ti0 >> 8) & 0xFF] ^ T3[ti1 & 0xFF] ^ K[26]; - a3 = T0[ti3 >>> 24] ^ T1[(ti0 >> 16) & 0xFF] - ^ T2[(ti1 >> 8) & 0xFF] ^ T3[ti2 & 0xFF] ^ K[27]; - - ti0 = T0[a0 >>> 24] ^ T1[(a1 >> 16) & 0xFF] - ^ T2[(a2 >> 8) & 0xFF] ^ T3[a3 & 0xFF] ^ K[28]; - ti1 = T0[a1 >>> 24] ^ T1[(a2 >> 16) & 0xFF] - ^ T2[(a3 >> 8) & 0xFF] ^ T3[a0 & 0xFF] ^ K[29]; - ti2 = T0[a2 >>> 24] ^ T1[(a3 >> 16) & 0xFF] - ^ T2[(a0 >> 8) & 0xFF] ^ T3[a1 & 0xFF] ^ K[30]; - ti3 = T0[a3 >>> 24] ^ T1[(a0 >> 16) & 0xFF] - ^ T2[(a1 >> 8) & 0xFF] ^ T3[a2 & 0xFF] ^ K[31]; - - a0 = T0[ti0 >>> 24] ^ T1[(ti1 >> 16) & 0xFF] - ^ T2[(ti2 >> 8) & 0xFF] ^ T3[ti3 & 0xFF] ^ K[32]; - a1 = T0[ti1 >>> 24] ^ T1[(ti2 >> 16) & 0xFF] - ^ T2[(ti3 >> 8) & 0xFF] ^ T3[ti0 & 0xFF] ^ K[33]; - a2 = T0[ti2 >>> 24] ^ T1[(ti3 >> 16) & 0xFF] - ^ T2[(ti0 >> 8) & 0xFF] ^ T3[ti1 & 0xFF] ^ K[34]; - a3 = T0[ti3 >>> 24] ^ T1[(ti0 >> 16) & 0xFF] - ^ T2[(ti1 >> 8) & 0xFF] ^ T3[ti2 & 0xFF] ^ K[35]; - - ti0 = T0[a0 >>> 24] ^ T1[(a1 >> 16) & 0xFF] - ^ T2[(a2 >> 8) & 0xFF] ^ T3[a3 & 0xFF] ^ K[36]; - ti1 = T0[a1 >>> 24] ^ T1[(a2 >> 16) & 0xFF] - ^ T2[(a3 >> 8) & 0xFF] ^ T3[a0 & 0xFF] ^ K[37]; - ti2 = T0[a2 >>> 24] ^ T1[(a3 >> 16) & 0xFF] - ^ T2[(a0 >> 8) & 0xFF] ^ T3[a1 & 0xFF] ^ K[38]; - ti3 = T0[a3 >>> 24] ^ T1[(a0 >> 16) & 0xFF] - ^ T2[(a1 >> 8) & 0xFF] ^ T3[a2 & 0xFF] ^ K[39]; - - if (rounds > AES_128_ROUNDS) { - a0 = T0[ti0 >>> 24] ^ T1[(ti1 >> 16) & 0xFF] - ^ T2[(ti2 >> 8) & 0xFF] ^ T3[ti3 & 0xFF] ^ K[40]; - a1 = T0[ti1 >>> 24] ^ T1[(ti2 >> 16) & 0xFF] - ^ T2[(ti3 >> 8) & 0xFF] ^ T3[ti0 & 0xFF] ^ K[41]; - a2 = T0[ti2 >>> 24] ^ T1[(ti3 >> 16) & 0xFF] - ^ T2[(ti0 >> 8) & 0xFF] ^ T3[ti1 & 0xFF] ^ K[42]; - a3 = T0[ti3 >>> 24] ^ T1[(ti0 >> 16) & 0xFF] - ^ T2[(ti1 >> 8) & 0xFF] ^ T3[ti2 & 0xFF] ^ K[43]; - - ti0 = T0[a0 >>> 24] ^ T1[(a1 >> 16) & 0xFF] - ^ T2[(a2 >> 8) & 0xFF] ^ T3[a3 & 0xFF] ^ K[44]; - ti1 = T0[a1 >>> 24] ^ T1[(a2 >> 16) & 0xFF] - ^ T2[(a3 >> 8) & 0xFF] ^ T3[a0 & 0xFF] ^ K[45]; - ti2 = T0[a2 >>> 24] ^ T1[(a3 >> 16) & 0xFF] - ^ T2[(a0 >> 8) & 0xFF] ^ T3[a1 & 0xFF] ^ K[46]; - ti3 = T0[a3 >>> 24] ^ T1[(a0 >> 16) & 0xFF] - ^ T2[(a1 >> 8) & 0xFF] ^ T3[a2 & 0xFF] ^ K[47]; - } - if (rounds > AES_192_ROUNDS) { - a0 = T0[ti0 >>> 24] ^ T1[(ti1 >> 16) & 0xFF] - ^ T2[(ti2 >> 8) & 0xFF] ^ T3[ti3 & 0xFF] ^ K[48]; - a1 = T0[ti1 >>> 24] ^ T1[(ti2 >> 16) & 0xFF] - ^ T2[(ti3 >> 8) & 0xFF] ^ T3[ti0 & 0xFF] ^ K[49]; - a2 = T0[ti2 >>> 24] ^ T1[(ti3 >> 16) & 0xFF] - ^ T2[(ti0 >> 8) & 0xFF] ^ T3[ti1 & 0xFF] ^ K[50]; - a3 = T0[ti3 >>> 24] ^ T1[(ti0 >> 16) & 0xFF] - ^ T2[(ti1 >> 8) & 0xFF] ^ T3[ti2 & 0xFF] ^ K[51]; - - ti0 = T0[a0 >>> 24] ^ T1[(a1 >> 16) & 0xFF] - ^ T2[(a2 >> 8) & 0xFF] ^ T3[a3 & 0xFF] ^ K[52]; - ti1 = T0[a1 >>> 24] ^ T1[(a2 >> 16) & 0xFF] - ^ T2[(a3 >> 8) & 0xFF] ^ T3[a0 & 0xFF] ^ K[53]; - ti2 = T0[a2 >>> 24] ^ T1[(a3 >> 16) & 0xFF] - ^ T2[(a0 >> 8) & 0xFF] ^ T3[a1 & 0xFF] ^ K[54]; - ti3 = T0[a3 >>> 24] ^ T1[(a0 >> 16) & 0xFF] - ^ T2[(a1 >> 8) & 0xFF] ^ T3[a2 & 0xFF] ^ K[55]; - } - - a0 = T2[ti0 >>> 24] & 0xFF000000 - ^ T3[(ti1 >> 16) & 0xFF] & 0xFF0000 - ^ T0[(ti2 >> 8) & 0xFF] & 0xFF00 - ^ T1[ti3 & 0xFF] & 0xFF ^ K[w]; - a1 = T2[ti1 >>> 24] & 0xFF000000 - ^ T3[(ti2 >> 16) & 0xFF] & 0xFF0000 - ^ T0[(ti3 >> 8) & 0xFF] & 0xFF00 - ^ T1[ti0 & 0xFF] & 0xFF ^ K[w + 1]; - a2 = T2[ti2 >>> 24] & 0xFF000000 - ^ T3[(ti3 >> 16) & 0xFF] & 0xFF0000 - ^ T0[(ti0 >> 8) & 0xFF] & 0xFF00 - ^ T1[ti1 & 0xFF] & 0xFF ^ K[w + 2]; - a3 = T2[ti3 >>> 24] & 0xFF000000 - ^ T3[(ti0 >> 16) & 0xFF] & 0xFF0000 - ^ T0[(ti1 >> 8) & 0xFF] & 0xFF00 - ^ T1[ti2 & 0xFF] & 0xFF ^ K[w + 3]; - - c[co] = (byte) (a0 >>> 24); - c[co + 1] = (byte) ((a0 >> 16) & 0xFF); - c[co + 2] = (byte) ((a0 >> 8) & 0xFF); - c[co + 3] = (byte) (a0 & 0xFF); - c[co + 4] = (byte) (a1 >>> 24); - c[co + 5] = (byte) ((a1 >> 16) & 0xFF); - c[co + 6] = (byte) ((a1 >> 8) & 0xFF); - c[co + 7] = (byte) (a1 & 0xFF); - c[co + 8] = (byte) (a2 >>> 24); - c[co + 9] = (byte) ((a2 >> 16) & 0xFF); - c[co + 10] = (byte) ((a2 >> 8) & 0xFF); - c[co + 11] = (byte) (a2 & 0xFF); - c[co + 12] = (byte) (a3 >> 24); - c[co + 13] = (byte) ((a3 >> 16) & 0xFF); - c[co + 14] = (byte) ((a3 >> 8) & 0xFF); - c[co + 15] = (byte) (a3 & 0xFF); - } - - /** - * Method for one block of decryption. - * - * @param c [in] the ciphertext to be decrypted. - * @param co [in] the ciphertext offset in the array of bytes. - * @param p [out] the plaintext output. - * @param po [in] the plaintext offset in the array of bytes. - */ - @IntrinsicCandidate - private void implDecryptBlock(byte[] c, int co, byte[] p, int po) { - int ti0, ti1, ti2, ti3; - int a0, a1, a2, a3; - - ti0 = ((c[co] & 0xFF) << 24) ^ ((c[co + 1] & 0xFF) << 16) - ^ ((c[co + 2] & 0xFF) << 8) ^ (c[co + 3] & 0xFF) ^ K[4]; - ti1 = ((c[co + 4] & 0xFF) << 24) ^ ((c[co + 5] & 0xFF) << 16) - ^ ((c[co + 6] & 0xFF) << 8) ^ (c[co + 7] & 0xFF) ^ K[5]; - ti2 = ((c[co + 8] & 0xFF) << 24) ^ ((c[co + 9] & 0xFF) << 16) - ^ ((c[co + 10] & 0xFF) << 8) ^ (c[co + 11] & 0xFF) ^ K[6]; - ti3 = ((c[co + 12] & 0xFF) << 24) ^ ((c[co + 13] & 0xFF) << 16) - ^ ((c[co + 14] & 0xFF) << 8) ^ (c[co + 15] & 0xFF) ^ K[7]; - - a0 = TI0[ti0 >>> 24] ^ TI1[(ti3 >> 16) & 0xFF] - ^ TI2[(ti2 >> 8) & 0xFF] ^ TI3[ti1 & 0xFF] ^ K[8]; - a1 = TI0[ti1 >>> 24] ^ TI1[(ti0 >> 16) & 0xFF] - ^ TI2[(ti3 >> 8) & 0xFF] ^ TI3[ti2 & 0xFF] ^ K[9]; - a2 = TI0[ti2 >>> 24] ^ TI1[(ti1 >> 16) & 0xFF] - ^ TI2[(ti0 >> 8) & 0xFF] ^ TI3[ti3 & 0xFF] ^ K[10]; - a3 = TI0[ti3 >>> 24] ^ TI1[(ti2 >> 16) & 0xFF] - ^ TI2[(ti1 >> 8) & 0xFF] ^ TI3[ti0 & 0xFF] ^ K[11]; - - ti0 = TI0[a0 >>> 24] ^ TI1[(a3 >> 16) & 0xFF] - ^ TI2[(a2 >> 8) & 0xFF] ^ TI3[a1 & 0xFF] ^ K[12]; - ti1 = TI0[a1 >>> 24] ^ TI1[(a0 >> 16) & 0xFF] - ^ TI2[(a3 >> 8) & 0xFF] ^ TI3[a2 & 0xFF] ^ K[13]; - ti2 = TI0[a2 >>> 24] ^ TI1[(a1 >> 16) & 0xFF] - ^ TI2[(a0 >> 8) & 0xFF] ^ TI3[a3 & 0xFF] ^ K[14]; - ti3 = TI0[a3 >>> 24] ^ TI1[(a2 >> 16) & 0xFF] - ^ TI2[(a1 >> 8) & 0xFF] ^ TI3[a0 & 0xFF] ^ K[15]; - - a0 = TI0[ti0 >>> 24] ^ TI1[(ti3 >> 16) & 0xFF] - ^ TI2[(ti2 >> 8) & 0xFF] ^ TI3[ti1 & 0xFF] ^ K[16]; - a1 = TI0[ti1 >>> 24] ^ TI1[(ti0 >> 16) & 0xFF] - ^ TI2[(ti3 >> 8) & 0xFF] ^ TI3[ti2 & 0xFF] ^ K[17]; - a2 = TI0[ti2 >>> 24] ^ TI1[(ti1 >> 16) & 0xFF] - ^ TI2[(ti0 >> 8) & 0xFF] ^ TI3[ti3 & 0xFF] ^ K[18]; - a3 = TI0[ti3 >>> 24] ^ TI1[(ti2 >> 16) & 0xFF] - ^ TI2[(ti1 >> 8) & 0xFF] ^ TI3[ti0 & 0xFF] ^ K[19]; - - ti0 = TI0[a0 >>> 24] ^ TI1[(a3 >> 16) & 0xFF] - ^ TI2[(a2 >> 8) & 0xFF] ^ TI3[a1 & 0xFF] ^ K[20]; - ti1 = TI0[a1 >>> 24] ^ TI1[(a0 >> 16) & 0xFF] - ^ TI2[(a3 >> 8) & 0xFF] ^ TI3[a2 & 0xFF] ^ K[21]; - ti2 = TI0[a2 >>> 24] ^ TI1[(a1 >> 16) & 0xFF] - ^ TI2[(a0 >> 8) & 0xFF] ^ TI3[a3 & 0xFF] ^ K[22]; - ti3 = TI0[a3 >>> 24] ^ TI1[(a2 >> 16) & 0xFF] - ^ TI2[(a1 >> 8) & 0xFF] ^ TI3[a0 & 0xFF] ^ K[23]; - - a0 = TI0[ti0 >>> 24] ^ TI1[(ti3 >> 16) & 0xFF] - ^ TI2[(ti2 >> 8) & 0xFF] ^ TI3[ti1 & 0xFF] ^ K[24]; - a1 = TI0[ti1 >>> 24] ^ TI1[(ti0 >> 16) & 0xFF] - ^ TI2[(ti3 >> 8) & 0xFF] ^ TI3[ti2 & 0xFF] ^ K[25]; - a2 = TI0[ti2 >>> 24] ^ TI1[(ti1 >> 16) & 0xFF] - ^ TI2[(ti0 >> 8) & 0xFF] ^ TI3[ti3 & 0xFF] ^ K[26]; - a3 = TI0[ti3 >>> 24] ^ TI1[(ti2 >> 16) & 0xFF] - ^ TI2[(ti1 >> 8) & 0xFF] ^ TI3[ti0 & 0xFF] ^ K[27]; - - ti0 = TI0[a0 >>> 24] ^ TI1[(a3 >> 16) & 0xFF] - ^ TI2[(a2 >> 8) & 0xFF] ^ TI3[a1 & 0xFF] ^ K[28]; - ti1 = TI0[a1 >>> 24] ^ TI1[(a0 >> 16) & 0xFF] - ^ TI2[(a3 >> 8) & 0xFF] ^ TI3[a2 & 0xFF] ^ K[29]; - ti2 = TI0[a2 >>> 24] ^ TI1[(a1 >> 16) & 0xFF] - ^ TI2[(a0 >> 8) & 0xFF] ^ TI3[a3 & 0xFF] ^ K[30]; - ti3 = TI0[a3 >>> 24] ^ TI1[(a2 >> 16) & 0xFF] - ^ TI2[(a1 >> 8) & 0xFF] ^ TI3[a0 & 0xFF] ^ K[31]; - - a0 = TI0[ti0 >>> 24] ^ TI1[(ti3 >> 16) & 0xFF] - ^ TI2[(ti2 >> 8) & 0xFF] ^ TI3[ti1 & 0xFF] ^ K[32]; - a1 = TI0[ti1 >>> 24] ^ TI1[(ti0 >> 16) & 0xFF] - ^ TI2[(ti3 >> 8) & 0xFF] ^ TI3[ti2 & 0xFF] ^ K[33]; - a2 = TI0[ti2 >>> 24] ^ TI1[(ti1 >> 16) & 0xFF] - ^ TI2[(ti0 >> 8) & 0xFF] ^ TI3[ti3 & 0xFF] ^ K[34]; - a3 = TI0[ti3 >>> 24] ^ TI1[(ti2 >> 16) & 0xFF] - ^ TI2[(ti1 >> 8) & 0xFF] ^ TI3[ti0 & 0xFF] ^ K[35]; - - ti0 = TI0[a0 >>> 24] ^ TI1[(a3 >> 16) & 0xFF] - ^ TI2[(a2 >> 8) & 0xFF] ^ TI3[a1 & 0xFF] ^ K[36]; - ti1 = TI0[a1 >>> 24] ^ TI1[(a0 >> 16) & 0xFF] - ^ TI2[(a3 >> 8) & 0xFF] ^ TI3[a2 & 0xFF] ^ K[37]; - ti2 = TI0[a2 >>> 24] ^ TI1[(a1 >> 16) & 0xFF] - ^ TI2[(a0 >> 8) & 0xFF] ^ TI3[a3 & 0xFF] ^ K[38]; - ti3 = TI0[a3 >>> 24] ^ TI1[(a2 >> 16) & 0xFF] - ^ TI2[(a1 >> 8) & 0xFF] ^ TI3[a0 & 0xFF] ^ K[39]; - - a0 = TI0[ti0 >>> 24] ^ TI1[(ti3 >> 16) & 0xFF] - ^ TI2[(ti2 >> 8) & 0xFF] ^ TI3[ti1 & 0xFF] ^ K[40]; - a1 = TI0[ti1 >>> 24] ^ TI1[(ti0 >> 16) & 0xFF] - ^ TI2[(ti3 >> 8) & 0xFF] ^ TI3[ti2 & 0xFF] ^ K[41]; - a2 = TI0[ti2 >>> 24] ^ TI1[(ti1 >> 16) & 0xFF] - ^ TI2[(ti0 >> 8) & 0xFF] ^ TI3[ti3 & 0xFF] ^ K[42]; - a3 = TI0[ti3 >>> 24] ^ TI1[(ti2 >> 16) & 0xFF] - ^ TI2[(ti1 >> 8) & 0xFF] ^ TI3[ti0 & 0xFF] ^ K[43]; - - if (rounds > AES_128_ROUNDS) { - ti0 = TI0[a0 >>> 24] ^ TI1[(a3 >> 16) & 0xFF] - ^ TI2[(a2 >> 8) & 0xFF] ^ TI3[a1 & 0xFF] ^ K[44]; - ti1 = TI0[a1 >>> 24] ^ TI1[(a0 >> 16) & 0xFF] - ^ TI2[(a3 >> 8) & 0xFF] ^ TI3[a2 & 0xFF] ^ K[45]; - ti2 = TI0[a2 >>> 24] ^ TI1[(a1 >> 16) & 0xFF] - ^ TI2[(a0 >> 8) & 0xFF] ^ TI3[a3 & 0xFF] ^ K[46]; - ti3 = TI0[a3 >>> 24] ^ TI1[(a2 >> 16) & 0xFF] - ^ TI2[(a1 >> 8) & 0xFF] ^ TI3[a0 & 0xFF] ^ K[47]; - - a0 = TI0[ti0 >>> 24] ^ TI1[(ti3 >> 16) & 0xFF] - ^ TI2[(ti2 >> 8) & 0xFF] ^ TI3[ti1 & 0xFF] ^ K[48]; - a1 = TI0[ti1 >>> 24] ^ TI1[(ti0 >> 16) & 0xFF] - ^ TI2[(ti3 >> 8) & 0xFF] ^ TI3[ti2 & 0xFF] ^ K[49]; - a2 = TI0[ti2 >>> 24] ^ TI1[(ti1 >> 16) & 0xFF] - ^ TI2[(ti0 >> 8) & 0xFF] ^ TI3[ti3 & 0xFF] ^ K[50]; - a3 = TI0[ti3 >>> 24] ^ TI1[(ti2 >> 16) & 0xFF] - ^ TI2[(ti1 >> 8) & 0xFF] ^ TI3[ti0 & 0xFF] ^ K[51]; - } - if (rounds > AES_192_ROUNDS) { - ti0 = TI0[a0 >>> 24] ^ TI1[(a3 >> 16) & 0xFF] - ^ TI2[(a2 >> 8) & 0xFF] ^ TI3[a1 & 0xFF] ^ K[52]; - ti1 = TI0[a1 >>> 24] ^ TI1[(a0 >> 16) & 0xFF] - ^ TI2[(a3 >> 8) & 0xFF] ^ TI3[a2 & 0xFF] ^ K[53]; - ti2 = TI0[a2 >>> 24] ^ TI1[(a1 >> 16) & 0xFF] - ^ TI2[(a0 >> 8) & 0xFF] ^ TI3[a3 & 0xFF] ^ K[54]; - ti3 = TI0[a3 >>> 24] ^ TI1[(a2 >> 16) & 0xFF] - ^ TI2[(a1 >> 8) & 0xFF] ^ TI3[a0 & 0xFF] ^ K[55]; - - a0 = TI0[ti0 >>> 24] ^ TI1[(ti3 >> 16) & 0xFF] - ^ TI2[(ti2 >> 8) & 0xFF] ^ TI3[ti1 & 0xFF] ^ K[56]; - a1 = TI0[ti1 >>> 24] ^ TI1[(ti0 >> 16) & 0xFF] - ^ TI2[(ti3 >> 8) & 0xFF] ^ TI3[ti2 & 0xFF] ^ K[57]; - a2 = TI0[ti2 >>> 24] ^ TI1[(ti1 >> 16) & 0xFF] - ^ TI2[(ti0 >> 8) & 0xFF] ^ TI3[ti3 & 0xFF] ^ K[58]; - a3 = TI0[ti3 >>> 24] ^ TI1[(ti2 >> 16) & 0xFF] - ^ TI2[(ti1 >> 8) & 0xFF] ^ TI3[ti0 & 0xFF] ^ K[59]; - } - - ti0 = TI4[a0 >>> 24] & 0xFF000000 ^ TI4[(a3 >> 16) & 0xFF] & 0xFF0000 - ^ TI4[(a2 >> 8) & 0xFF] & 0xFF00 ^ TI4[a1 & 0xFF] & 0xFF ^ K[0]; - ti1 = TI4[a1 >>> 24] & 0xFF000000 ^ TI4[(a0 >> 16) & 0xFF] & 0xFF0000 - ^ TI4[(a3 >> 8) & 0xFF] & 0xFF00 ^ TI4[a2 & 0xFF] & 0xFF ^ K[1]; - ti2 = TI4[a2 >>> 24] & 0xFF000000 ^ TI4[(a1 >> 16) & 0xFF] & 0xFF0000 - ^ TI4[(a0 >> 8) & 0xFF] & 0xFF00 ^ TI4[a3 & 0xFF] & 0xFF ^ K[2]; - ti3 = TI4[a3 >>> 24] & 0xFF000000 ^ TI4[(a2 >> 16) & 0xFF] & 0xFF0000 - ^ TI4[(a1 >> 8) & 0xFF] & 0xFF00 ^ TI4[a0 & 0xFF] & 0xFF ^ K[3]; - - p[po] = (byte) (ti0 >>> 24); - p[po + 1] = (byte) ((ti0 >> 16) & 0xFF); - p[po + 2] = (byte) ((ti0 >> 8) & 0xFF); - p[po + 3] = (byte) (ti0 & 0xFF); - p[po + 4] = (byte) (ti1 >>> 24); - p[po + 5] = (byte) ((ti1 >> 16) & 0xFF); - p[po + 6] = (byte) ((ti1 >> 8) & 0xFF); - p[po + 7] = (byte) (ti1 & 0xFF); - p[po + 8] = (byte) (ti2 >>> 24); - p[po + 9] = (byte) ((ti2 >> 16) & 0xFF); - p[po + 10] = (byte) ((ti2 >> 8) & 0xFF); - p[po + 11] = (byte) (ti2 & 0xFF); - p[po + 12] = (byte) (ti3 >>> 24); - p[po + 13] = (byte) ((ti3 >> 16) & 0xFF); - p[po + 14] = (byte) ((ti3 >> 8) & 0xFF); - p[po + 15] = (byte) (ti3 & 0xFF); - } - - /** - * Method for one block of encryption. - * - * @param plain [in] the plaintext to be encrypted. - * @param pOff [in] the plaintext offset in the array of bytes. - * @param cipher [out] the encrypted ciphertext output. - * @param cOff [in] the ciphertext offset in the array of bytes. - */ - void encryptBlock(byte[] plain, int pOff, byte[] cipher, int cOff) { - implEncryptBlock(plain, pOff, cipher, cOff); - } - - /** - * Method for one block of decryption. - * - * @param cipher [in] the ciphertext to be decrypted. - * @param cOff [in] the ciphertext offset in the array of bytes. - * @param plain [out] the decrypted plaintext output. - * @param pOff [in] the plaintext offset in the array of bytes. - */ - void decryptBlock(byte[] cipher, int cOff, byte[] plain, int pOff) { - implDecryptBlock(cipher, cOff, plain, pOff); - } -} diff --git a/src/java.base/share/classes/com/sun/crypto/provider/GCTR.java b/src/java.base/share/classes/com/sun/crypto/provider/GCTR.java index 3f3373860f318..926a56c140b66 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/GCTR.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/GCTR.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,7 @@ * to 16 bytes. * * If any invariant is broken, failures can occur because the - * AES_Crypt.encryptBlock method can be intrinsified on the HotSpot VM + * AESCrypt.encryptBlock method can be intrinsified on the HotSpot VM * (see JDK-8067648 for details). * * The counter mode operations can be intrinsified and parallelized diff --git a/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java b/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java index 2f4df1eba03b4..3d1396121ad3e 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java @@ -102,7 +102,7 @@ abstract class GaloisCounterMode extends CipherSpi { /** * * @param keySize length of key. - * @param embeddedCipher Cipher object, such as AES_Crypt. + * @param embeddedCipher Cipher object, such as AESCrypt. */ GaloisCounterMode(int keySize, SymmetricCipher embeddedCipher) { blockCipher = embeddedCipher; @@ -198,7 +198,7 @@ protected int engineGetOutputSize(int inputLen) { protected int engineGetKeySize(Key key) throws InvalidKeyException { byte[] encoded = key.getEncoded(); Arrays.fill(encoded, (byte)0); - if (!AES_Crypt.isKeySizeValid(encoded.length)) { + if (!AESCrypt.isKeySizeValid(encoded.length)) { throw new InvalidKeyException("Invalid key length: " + encoded.length + " bytes"); } @@ -1693,25 +1693,25 @@ int decryptBlocks(GCMOperation op, byte[] in, int inOfs, int inLen, public static final class AESGCM extends GaloisCounterMode { public AESGCM() { - super(-1, new AES_Crypt()); + super(-1, new AESCrypt()); } } public static final class AES128 extends GaloisCounterMode { public AES128() { - super(16, new AES_Crypt()); + super(16, new AESCrypt()); } } public static final class AES192 extends GaloisCounterMode { public AES192() { - super(24, new AES_Crypt()); + super(24, new AESCrypt()); } } public static final class AES256 extends GaloisCounterMode { public AES256() { - super(32, new AES_Crypt()); + super(32, new AESCrypt()); } } diff --git a/src/java.base/share/classes/com/sun/crypto/provider/KeyWrapCipher.java b/src/java.base/share/classes/com/sun/crypto/provider/KeyWrapCipher.java index e0c1873213b46..ba2825fa36c2a 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/KeyWrapCipher.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/KeyWrapCipher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -137,7 +137,7 @@ private static byte[] checkKey(Key key, int fixedKeySize) } int keyLen = keyBytes.length; if (!key.getAlgorithm().equalsIgnoreCase("AES") || - !AES_Crypt.isKeySizeValid(keyLen) || + !AESCrypt.isKeySizeValid(keyLen) || (fixedKeySize != -1 && fixedKeySize != keyLen)) { throw new InvalidKeyException("Invalid key length: " + keyLen + " bytes"); diff --git a/src/java.base/share/classes/com/sun/crypto/provider/PBES2Core.java b/src/java.base/share/classes/com/sun/crypto/provider/PBES2Core.java index df37da2347f4a..6d2c4da3b8b25 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/PBES2Core.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/PBES2Core.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2023, 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 @@ -68,7 +68,7 @@ abstract class PBES2Core extends CipherSpi { if (cipherAlgo.equals("AES")) { blkSize = AESConstants.AES_BLOCK_SIZE; - cipher = new CipherCore(new AES_Crypt(), blkSize); + cipher = new CipherCore(new AESCrypt(), blkSize); switch(kdfAlgo) { case "HmacSHA1": diff --git a/src/java.base/share/classes/com/sun/crypto/provider/SymmetricCipher.java b/src/java.base/share/classes/com/sun/crypto/provider/SymmetricCipher.java index ad93679140ca6..7b428f86aa7bb 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/SymmetricCipher.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/SymmetricCipher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -36,7 +36,7 @@ * @author Jan Luehe * * - * @see AES_Crypt + * @see AESCrypt * @see DESCrypt * @see DESedeCrypt * @see BlowfishCrypt diff --git a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java index f1da102236a34..d317557cbb19c 100644 --- a/src/java.base/share/classes/java/lang/AbstractStringBuilder.java +++ b/src/java.base/share/classes/java/lang/AbstractStringBuilder.java @@ -1448,8 +1448,8 @@ public AbstractStringBuilder insert(int dstOffset, CharSequence s, shift(currValue, coder, count, dstOffset, len); count += len; // Coder of CharSequence may be a mismatch, requiring the value array to be inflated - byte[] newValue = (s instanceof String str && str.length() == len) - ? putStringAt(currValue, coder, count, dstOffset, str) + byte[] newValue = (s instanceof String str) + ? putStringAt(currValue, coder, count, dstOffset, str, start, end) : putCharsAt(currValue, coder, count, dstOffset, s, start, end); if (currValue != newValue) { this.coder = UTF16; @@ -1928,10 +1928,10 @@ private static byte[] inflateIfNeededFor(byte[] value, int count, byte coder, by * @param index the index to insert the string * @param str the string */ - private static byte[] putStringAt(byte[] value, byte coder, int count, int index, String str) { + private static byte[] putStringAt(byte[] value, byte coder, int count, int index, String str, int off, int end) { byte[] newValue = inflateIfNeededFor(value, count, coder, str.coder()); coder = (newValue == value) ? coder : UTF16; - str.getBytes(newValue, 0, index, coder, str.length()); + str.getBytes(newValue, off, index, coder, end - off); return newValue; } diff --git a/src/java.base/share/classes/java/lang/Byte.java b/src/java.base/share/classes/java/lang/Byte.java index d9913e354a48f..accd448a0cdc5 100644 --- a/src/java.base/share/classes/java/lang/Byte.java +++ b/src/java.base/share/classes/java/lang/Byte.java @@ -55,6 +55,8 @@ * use instances for synchronization, or unpredictable behavior may * occur. For example, in a future release, synchronization may fail. * + * @author Nakul Saraiya + * @author Joseph D. Darcy * @see java.lang.Number * @since 1.1 */ diff --git a/src/java.base/share/classes/java/lang/Double.java b/src/java.base/share/classes/java/lang/Double.java index 53b027dd773d9..661a0ceb42b08 100644 --- a/src/java.base/share/classes/java/lang/Double.java +++ b/src/java.base/share/classes/java/lang/Double.java @@ -1,6 +1,5 @@ /* * Copyright (c) 1994, 2025, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2025, Alibaba Group Holding Limited. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,7 +33,6 @@ import jdk.internal.math.FloatingDecimal; import jdk.internal.math.DoubleConsts; import jdk.internal.math.DoubleToDecimal; -import jdk.internal.util.DecimalDigits; import jdk.internal.vm.annotation.IntrinsicCandidate; /** @@ -354,6 +352,9 @@ * @spec https://standards.ieee.org/ieee/754/6210/ * IEEE Standard for Floating-Point Arithmetic * + * @author Lee Boynton + * @author Arthur van Hoff + * @author Joseph D. Darcy * @since 1.0 */ @jdk.internal.ValueBased @@ -694,6 +695,7 @@ public static String toString(double d) { * @param d the {@code double} to be converted. * @return a hex string representation of the argument. * @since 1.5 + * @author Joseph D. Darcy */ public static String toHexString(double d) { /* @@ -701,80 +703,56 @@ public static String toHexString(double d) { * 7.19.6.1; however, the output of this method is more * tightly specified. */ - if (!isFinite(d)) { + if (!isFinite(d) ) // For infinity and NaN, use the decimal output. return Double.toString(d); + else { + // Initialized to maximum size of output. + StringBuilder answer = new StringBuilder(24); + + if (Math.copySign(1.0, d) == -1.0) // value is negative, + answer.append("-"); // so append sign info + + answer.append("0x"); + + d = Math.abs(d); + + if(d == 0.0) { + answer.append("0.0p0"); + } else { + boolean subnormal = (d < Double.MIN_NORMAL); + + // Isolate significand bits and OR in a high-order bit + // so that the string representation has a known + // length. + long signifBits = (Double.doubleToLongBits(d) + & DoubleConsts.SIGNIF_BIT_MASK) | + 0x1000000000000000L; + + // Subnormal values have a 0 implicit bit; normal + // values have a 1 implicit bit. + answer.append(subnormal ? "0." : "1."); + + // Isolate the low-order 13 digits of the hex + // representation. If all the digits are zero, + // replace with a single 0; otherwise, remove all + // trailing zeros. + String signif = Long.toHexString(signifBits).substring(3,16); + answer.append(signif.equals("0000000000000") ? // 13 zeros + "0": + signif.replaceFirst("0{1,12}$", "")); + + answer.append('p'); + // If the value is subnormal, use the E_min exponent + // value for double; otherwise, extract and report d's + // exponent (the representation of a subnormal uses + // E_min -1). + answer.append(subnormal ? + Double.MIN_EXPONENT: + Math.getExponent(d)); + } + return answer.toString(); } - - long doubleToLongBits = Double.doubleToLongBits(d); - boolean negative = doubleToLongBits < 0; - - if (d == 0.0) { - return negative ? "-0x0.0p0" : "0x0.0p0"; - } - d = Math.abs(d); - // Check if the value is subnormal (less than the smallest normal value) - boolean subnormal = d < Double.MIN_NORMAL; - - // Isolate significand bits and OR in a high-order bit - // so that the string representation has a known length. - // This ensures we always have 13 hex digits to work with (52 bits / 4 bits per hex digit) - long signifBits = doubleToLongBits & DoubleConsts.SIGNIF_BIT_MASK; - - // Calculate the number of trailing zeros in the significand (in groups of 4 bits) - // This is used to remove trailing zeros from the hex representation - // We limit to 12 because we want to keep at least 1 hex digit (13 total - 12 = 1) - // assert 0 <= trailingZeros && trailingZeros <= 12 - int trailingZeros = Long.numberOfTrailingZeros(signifBits | 1L << 4 * 12) >> 2; - - // Determine the exponent value based on whether the number is subnormal or normal - // Subnormal numbers use the minimum exponent, normal numbers use the actual exponent - int exp = subnormal ? Double.MIN_EXPONENT : Math.getExponent(d); - - // Calculate the total length of the resulting string: - // Sign (optional) + prefix "0x" + implicit bit + "." + hex digits + "p" + exponent - int charlen = (negative ? 1 : 0) // sign character - + 4 // "0x1." or "0x0." - + 13 - trailingZeros // hex digits (13 max, minus trailing zeros) - + 1 // "p" - + DecimalDigits.stringSize(exp) // exponent - ; - - // Create a byte array to hold the result characters - byte[] chars = new byte[charlen]; - int index = 0; - - // Add the sign character if the number is negative - if (negative) { // value is negative - chars[index++] = '-'; - } - - // Add the prefix and the implicit bit ('1' for normal, '0' for subnormal) - // Subnormal values have a 0 implicit bit; normal values have a 1 implicit bit. - chars[index ] = '0'; // Hex prefix - chars[index + 1] = 'x'; // Hex prefix - chars[index + 2] = (byte) (subnormal ? '0' : '1'); // Implicit bit - chars[index + 3] = '.'; // Decimal point - index += 4; - - // Convert significand to hex digits manually to avoid creating temporary strings - // Extract the 13 hex digits (52 bits) from signifBits - // We need to extract bits 48-51, 44-47, ..., 0-3 (13 groups of 4 bits) - for (int sh = 4 * 12, end = 4 * trailingZeros; sh >= end; sh -= 4) { - // Extract 4 bits at a time from left to right - // Shift right by sh positions and mask with 0xF - // Integer.digits maps values 0-15 to '0'-'f' characters - chars[index++] = Integer.digits[((int)(signifBits >> sh)) & 0xF]; - } - - // Add the exponent indicator - chars[index] = 'p'; - - // Append the exponent value to the character array - // This method writes the decimal representation of exp directly into the byte array - DecimalDigits.uncheckedGetCharsLatin1(exp, charlen, chars); - - return String.newStringWithLatin1Bytes(chars); } /** diff --git a/src/java.base/share/classes/java/lang/Float.java b/src/java.base/share/classes/java/lang/Float.java index c553dc41c2c91..db694571567b0 100644 --- a/src/java.base/share/classes/java/lang/Float.java +++ b/src/java.base/share/classes/java/lang/Float.java @@ -70,6 +70,9 @@ * @spec https://standards.ieee.org/ieee/754/6210/ * IEEE Standard for Floating-Point Arithmetic * + * @author Lee Boynton + * @author Arthur van Hoff + * @author Joseph D. Darcy * @since 1.0 */ @jdk.internal.ValueBased @@ -408,6 +411,7 @@ public static String toString(float f) { * @param f the {@code float} to be converted. * @return a hex string representation of the argument. * @since 1.5 + * @author Joseph D. Darcy */ public static String toHexString(float f) { if (Math.abs(f) < Float.MIN_NORMAL diff --git a/src/java.base/share/classes/java/lang/Integer.java b/src/java.base/share/classes/java/lang/Integer.java index 20d1edb6d5ff3..41487a469b6a0 100644 --- a/src/java.base/share/classes/java/lang/Integer.java +++ b/src/java.base/share/classes/java/lang/Integer.java @@ -68,6 +68,10 @@ * Delight, (Addison Wesley, 2002) and Hacker's * Delight, Second Edition, (Pearson Education, 2013). * + * @author Lee Boynton + * @author Arthur van Hoff + * @author Josh Bloch + * @author Joseph D. Darcy * @since 1.0 */ @jdk.internal.ValueBased @@ -363,9 +367,15 @@ private static String toUnsignedString0(int val, int shift) { // assert shift > 0 && shift <=5 : "Illegal shift value"; int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val); int chars = Math.max(((mag + (shift - 1)) / shift), 1); - byte[] buf = new byte[chars]; - formatUnsignedInt(val, shift, buf, chars); - return String.newStringWithLatin1Bytes(buf); + if (COMPACT_STRINGS) { + byte[] buf = new byte[chars]; + formatUnsignedInt(val, shift, buf, chars); + return new String(buf, LATIN1); + } else { + byte[] buf = new byte[chars * 2]; + formatUnsignedIntUTF16(val, shift, buf, chars); + return new String(buf, UTF16); + } } /** @@ -388,6 +398,26 @@ private static void formatUnsignedInt(int val, int shift, byte[] buf, int len) { } while (charPos > 0); } + /** + * Format an {@code int} (treated as unsigned) into a byte buffer (UTF16 version). If + * {@code len} exceeds the formatted ASCII representation of {@code val}, + * {@code buf} will be padded with leading zeroes. + * + * @param val the unsigned int to format + * @param shift the log2 of the base to format in (4 for hex, 3 for octal, 1 for binary) + * @param buf the byte buffer to write to + * @param len the number of characters to write + */ + private static void formatUnsignedIntUTF16(int val, int shift, byte[] buf, int len) { + int charPos = len; + int radix = 1 << shift; + int mask = radix - 1; + do { + StringUTF16.putChar(buf, --charPos, Integer.digits[val & mask]); + val >>>= shift; + } while (charPos > 0); + } + /** * Returns a {@code String} object representing the * specified integer. The argument is converted to signed decimal @@ -401,9 +431,15 @@ private static void formatUnsignedInt(int val, int shift, byte[] buf, int len) { @IntrinsicCandidate public static String toString(int i) { int size = DecimalDigits.stringSize(i); - byte[] buf = new byte[size]; - DecimalDigits.uncheckedGetCharsLatin1(i, size, buf); - return String.newStringWithLatin1Bytes(buf); + if (COMPACT_STRINGS) { + byte[] buf = new byte[size]; + DecimalDigits.uncheckedGetCharsLatin1(i, size, buf); + return new String(buf, LATIN1); + } else { + byte[] buf = new byte[size * 2]; + DecimalDigits.uncheckedGetCharsUTF16(i, size, buf); + return new String(buf, UTF16); + } } /** diff --git a/src/java.base/share/classes/java/lang/Long.java b/src/java.base/share/classes/java/lang/Long.java index b0477fdab6dab..2fb2d18a78c80 100644 --- a/src/java.base/share/classes/java/lang/Long.java +++ b/src/java.base/share/classes/java/lang/Long.java @@ -68,6 +68,10 @@ * Delight, (Addison Wesley, 2002) and Hacker's * Delight, Second Edition, (Pearson Education, 2013). * + * @author Lee Boynton + * @author Arthur van Hoff + * @author Josh Bloch + * @author Joseph D. Darcy * @since 1.0 */ @jdk.internal.ValueBased @@ -391,9 +395,15 @@ static String toUnsignedString0(long val, int shift) { // assert shift > 0 && shift <=5 : "Illegal shift value"; int mag = Long.SIZE - Long.numberOfLeadingZeros(val); int chars = Math.max(((mag + (shift - 1)) / shift), 1); - byte[] buf = new byte[chars]; - formatUnsignedLong0(val, shift, buf, 0, chars); - return String.newStringWithLatin1Bytes(buf); + if (COMPACT_STRINGS) { + byte[] buf = new byte[chars]; + formatUnsignedLong0(val, shift, buf, 0, chars); + return new String(buf, LATIN1); + } else { + byte[] buf = new byte[chars * 2]; + formatUnsignedLong0UTF16(val, shift, buf, 0, chars); + return new String(buf, UTF16); + } } /** @@ -417,6 +427,27 @@ private static void formatUnsignedLong0(long val, int shift, byte[] buf, int off } while (charPos > offset); } + /** + * Format a long (treated as unsigned) into a byte buffer (UTF16 version). If + * {@code len} exceeds the formatted ASCII representation of {@code val}, + * {@code buf} will be padded with leading zeroes. + * + * @param val the unsigned long to format + * @param shift the log2 of the base to format in (4 for hex, 3 for octal, 1 for binary) + * @param buf the byte buffer to write to + * @param offset the offset in the destination buffer to start at + * @param len the number of characters to write + */ + private static void formatUnsignedLong0UTF16(long val, int shift, byte[] buf, int offset, int len) { + int charPos = offset + len; + int radix = 1 << shift; + int mask = radix - 1; + do { + StringUTF16.putChar(buf, --charPos, Integer.digits[((int) val) & mask]); + val >>>= shift; + } while (charPos > offset); + } + /** * Returns a {@code String} object representing the specified * {@code long}. The argument is converted to signed decimal @@ -429,9 +460,15 @@ private static void formatUnsignedLong0(long val, int shift, byte[] buf, int off */ public static String toString(long i) { int size = DecimalDigits.stringSize(i); - byte[] buf = new byte[size]; - DecimalDigits.uncheckedGetCharsLatin1(i, size, buf); - return String.newStringWithLatin1Bytes(buf); + if (COMPACT_STRINGS) { + byte[] buf = new byte[size]; + DecimalDigits.uncheckedGetCharsLatin1(i, size, buf); + return new String(buf, LATIN1); + } else { + byte[] buf = new byte[size * 2]; + DecimalDigits.uncheckedGetCharsUTF16(i, size, buf); + return new String(buf, UTF16); + } } /** diff --git a/src/java.base/share/classes/java/lang/Math.java b/src/java.base/share/classes/java/lang/Math.java index 0f39ecf0a8a69..ef5d1214b115e 100644 --- a/src/java.base/share/classes/java/lang/Math.java +++ b/src/java.base/share/classes/java/lang/Math.java @@ -2529,6 +2529,7 @@ public static float fma(float a, float b, float c) { * * @param d the floating-point value whose ulp is to be returned * @return the size of an ulp of the argument + * @author Joseph D. Darcy * @since 1.5 */ public static double ulp(double d) { @@ -2575,6 +2576,7 @@ public static double ulp(double d) { * * @param f the floating-point value whose ulp is to be returned * @return the size of an ulp of the argument + * @author Joseph D. Darcy * @since 1.5 */ public static float ulp(float f) { @@ -2615,6 +2617,7 @@ public static float ulp(float f) { * * @param d the floating-point value whose signum is to be returned * @return the signum function of the argument + * @author Joseph D. Darcy * @since 1.5 */ @IntrinsicCandidate @@ -2636,6 +2639,7 @@ public static double signum(double d) { * * @param f the floating-point value whose signum is to be returned * @return the signum function of the argument + * @author Joseph D. Darcy * @since 1.5 */ @IntrinsicCandidate diff --git a/src/java.base/share/classes/java/lang/Short.java b/src/java.base/share/classes/java/lang/Short.java index 4c64427b6dff4..f0ae8b28e4594 100644 --- a/src/java.base/share/classes/java/lang/Short.java +++ b/src/java.base/share/classes/java/lang/Short.java @@ -55,6 +55,8 @@ * use instances for synchronization, or unpredictable behavior may * occur. For example, in a future release, synchronization may fail. * + * @author Nakul Saraiya + * @author Joseph D. Darcy * @see java.lang.Number * @since 1.1 */ diff --git a/src/java.base/share/classes/java/lang/StrictMath.java b/src/java.base/share/classes/java/lang/StrictMath.java index 499fce73aee10..266d98e394744 100644 --- a/src/java.base/share/classes/java/lang/StrictMath.java +++ b/src/java.base/share/classes/java/lang/StrictMath.java @@ -101,6 +101,7 @@ * @spec https://standards.ieee.org/ieee/754/6210/ * IEEE Standard for Floating-Point Arithmetic * + * @author Joseph D. Darcy * @since 1.3 */ public final class StrictMath { @@ -492,6 +493,7 @@ private static double floorOrCeil(double a, * @param a a value. * @return the closest floating-point value to {@code a} that is * equal to a mathematical integer. + * @author Joseph D. Darcy */ public static double rint(double a) { /* @@ -2012,6 +2014,7 @@ public static float fma(float a, float b, float c) { * * @param d the floating-point value whose ulp is to be returned * @return the size of an ulp of the argument + * @author Joseph D. Darcy * @since 1.5 */ public static double ulp(double d) { @@ -2038,6 +2041,7 @@ public static double ulp(double d) { * * @param f the floating-point value whose ulp is to be returned * @return the size of an ulp of the argument + * @author Joseph D. Darcy * @since 1.5 */ public static float ulp(float f) { @@ -2058,6 +2062,7 @@ public static float ulp(float f) { * * @param d the floating-point value whose signum is to be returned * @return the signum function of the argument + * @author Joseph D. Darcy * @since 1.5 */ public static double signum(double d) { @@ -2078,6 +2083,7 @@ public static double signum(double d) { * * @param f the floating-point value whose signum is to be returned * @return the signum function of the argument + * @author Joseph D. Darcy * @since 1.5 */ public static float signum(float f) { diff --git a/src/java.base/share/classes/java/lang/runtime/ObjectMethods.java b/src/java.base/share/classes/java/lang/runtime/ObjectMethods.java index 18aa6f29f1f09..24b55600954d2 100644 --- a/src/java.base/share/classes/java/lang/runtime/ObjectMethods.java +++ b/src/java.base/share/classes/java/lang/runtime/ObjectMethods.java @@ -25,26 +25,18 @@ package java.lang.runtime; -import java.lang.classfile.ClassFile; -import java.lang.classfile.ClassHierarchyResolver; -import java.lang.classfile.Opcode; -import java.lang.constant.ClassDesc; -import java.lang.constant.MethodTypeDesc; import java.lang.invoke.ConstantCallSite; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.lang.invoke.StringConcatFactory; import java.lang.invoke.TypeDescriptor; -import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Objects; -import static java.lang.classfile.ClassFile.ACC_STATIC; -import static java.lang.constant.ConstantDescs.*; import static java.util.Objects.requireNonNull; /** @@ -66,18 +58,15 @@ private ObjectMethods() { } private static final MethodHandle TRUE = MethodHandles.constant(boolean.class, true); private static final MethodHandle ZERO = MethodHandles.zero(int.class); private static final MethodHandle CLASS_IS_INSTANCE; - private static final MethodHandle IS_NULL; - private static final MethodHandle IS_ARG0_NULL; - private static final MethodHandle IS_ARG1_NULL; + private static final MethodHandle OBJECTS_EQUALS; + private static final MethodHandle OBJECTS_HASHCODE; + private static final MethodHandle OBJECTS_TOSTRING; private static final MethodHandle OBJECT_EQ; private static final MethodHandle HASH_COMBINER; - private static final MethodType MT_OBJECT_BOOLEAN = MethodType.methodType(boolean.class, Object.class); - private static final MethodType MT_INT = MethodType.methodType(int.class); - private static final MethodTypeDesc MTD_OBJECT_BOOLEAN = MethodTypeDesc.of(CD_boolean, CD_Object); - private static final MethodTypeDesc MTD_INT = MethodTypeDesc.of(CD_int); private static final HashMap, MethodHandle> primitiveEquals = new HashMap<>(); private static final HashMap, MethodHandle> primitiveHashers = new HashMap<>(); + private static final HashMap, MethodHandle> primitiveToString = new HashMap<>(); static { try { @@ -87,12 +76,12 @@ private ObjectMethods() { } CLASS_IS_INSTANCE = publicLookup.findVirtual(Class.class, "isInstance", MethodType.methodType(boolean.class, Object.class)); - - var objectsIsNull = publicLookup.findStatic(Objects.class, "isNull", - MethodType.methodType(boolean.class, Object.class)); - IS_NULL = objectsIsNull; - IS_ARG0_NULL = MethodHandles.dropArguments(objectsIsNull, 1, Object.class); - IS_ARG1_NULL = MethodHandles.dropArguments(objectsIsNull, 0, Object.class); + OBJECTS_EQUALS = publicLookup.findStatic(Objects.class, "equals", + MethodType.methodType(boolean.class, Object.class, Object.class)); + OBJECTS_HASHCODE = publicLookup.findStatic(Objects.class, "hashCode", + MethodType.methodType(int.class, Object.class)); + OBJECTS_TOSTRING = publicLookup.findStatic(Objects.class, "toString", + MethodType.methodType(String.class, Object.class)); OBJECT_EQ = lookup.findStatic(OBJECT_METHODS_CLASS, "eq", MethodType.methodType(boolean.class, Object.class, Object.class)); @@ -132,6 +121,23 @@ private ObjectMethods() { } MethodType.methodType(int.class, double.class))); primitiveHashers.put(boolean.class, lookup.findStatic(Boolean.class, "hashCode", MethodType.methodType(int.class, boolean.class))); + + primitiveToString.put(byte.class, lookup.findStatic(Byte.class, "toString", + MethodType.methodType(String.class, byte.class))); + primitiveToString.put(short.class, lookup.findStatic(Short.class, "toString", + MethodType.methodType(String.class, short.class))); + primitiveToString.put(char.class, lookup.findStatic(Character.class, "toString", + MethodType.methodType(String.class, char.class))); + primitiveToString.put(int.class, lookup.findStatic(Integer.class, "toString", + MethodType.methodType(String.class, int.class))); + primitiveToString.put(long.class, lookup.findStatic(Long.class, "toString", + MethodType.methodType(String.class, long.class))); + primitiveToString.put(float.class, lookup.findStatic(Float.class, "toString", + MethodType.methodType(String.class, float.class))); + primitiveToString.put(double.class, lookup.findStatic(Double.class, "toString", + MethodType.methodType(String.class, double.class))); + primitiveToString.put(boolean.class, lookup.findStatic(Boolean.class, "toString", + MethodType.methodType(String.class, boolean.class))); } catch (ReflectiveOperationException e) { throw new RuntimeException(e); @@ -153,41 +159,24 @@ private static int hashCombiner(int x, int y) { private static boolean eq(boolean a, boolean b) { return a == b; } /** Get the method handle for combining two values of a given type */ - private static MethodHandle equalator(MethodHandles.Lookup lookup, Class clazz) throws Throwable { - if (clazz.isPrimitive()) - return primitiveEquals.get(clazz); - MethodType mt = MethodType.methodType(boolean.class, clazz, clazz); - return MethodHandles.guardWithTest(IS_ARG0_NULL.asType(mt), - IS_ARG1_NULL.asType(mt), - lookup.findVirtual(clazz, "equals", MT_OBJECT_BOOLEAN).asType(mt)); + private static MethodHandle equalator(Class clazz) { + return (clazz.isPrimitive() + ? primitiveEquals.get(clazz) + : OBJECTS_EQUALS.asType(MethodType.methodType(boolean.class, clazz, clazz))); } /** Get the hasher for a value of a given type */ - private static MethodHandle hasher(MethodHandles.Lookup lookup, Class clazz) throws Throwable { - if (clazz.isPrimitive()) - return primitiveHashers.get(clazz); - MethodType mt = MethodType.methodType(int.class, clazz); - return MethodHandles.guardWithTest(IS_NULL.asType(MethodType.methodType(boolean.class, clazz)), - MethodHandles.dropArguments(MethodHandles.zero(int.class), 0, clazz), - lookup.findVirtual(clazz, "hashCode", MT_INT).asType(mt)); + private static MethodHandle hasher(Class clazz) { + return (clazz.isPrimitive() + ? primitiveHashers.get(clazz) + : OBJECTS_HASHCODE.asType(MethodType.methodType(int.class, clazz))); } - // If this type must be a monomorphic receiver, that is, one that has no - // subtypes in the JVM. For example, Object-typed fields may have a more - // specific one type at runtime and thus need optimizations. - private static boolean isMonomorphic(Class type) { - // Includes primitives and final classes, but not arrays. - // All array classes are reported to be final, but Object[] can have subtypes like String[] - return Modifier.isFinal(type.getModifiers()) && !type.isArray(); - } - - private static String specializerClassName(Class targetClass, String kind) { - String name = targetClass.getName(); - if (targetClass.isHidden()) { - // use the original class name - name = name.replace('/', '_'); - } - return name + "$$" + kind + "Specializer"; + /** Get the stringifier for a value of a given type */ + private static MethodHandle stringifier(Class clazz) { + return (clazz.isPrimitive() + ? primitiveToString.get(clazz) + : OBJECTS_TOSTRING.asType(MethodType.methodType(String.class, clazz))); } /** @@ -196,8 +185,8 @@ private static String specializerClassName(Class targetClass, String kind) { * @param getters the list of getters * @return the method handle */ - private static MethodHandle makeEquals(MethodHandles.Lookup lookup, Class receiverClass, - List getters) throws Throwable { + private static MethodHandle makeEquals(Class receiverClass, + List getters) { MethodType rr = MethodType.methodType(boolean.class, receiverClass, receiverClass); MethodType ro = MethodType.methodType(boolean.class, receiverClass, Object.class); MethodHandle instanceFalse = MethodHandles.dropArguments(FALSE, 0, receiverClass, Object.class); // (RO)Z @@ -206,70 +195,8 @@ private static MethodHandle makeEquals(MethodHandles.Lookup lookup, Class rec MethodHandle isInstance = MethodHandles.dropArguments(CLASS_IS_INSTANCE.bindTo(receiverClass), 0, receiverClass); // (RO)Z MethodHandle accumulator = MethodHandles.dropArguments(TRUE, 0, receiverClass, receiverClass); // (RR)Z - int size = getters.size(); - MethodHandle[] equalators = new MethodHandle[size]; - boolean hasPolymorphism = false; - for (int i = 0; i < size; i++) { - var getter = getters.get(i); - var type = getter.type().returnType(); - if (isMonomorphic(type)) { - equalators[i] = equalator(lookup, type); - } else { - hasPolymorphism = true; - } - } - - // Currently, hotspot does not support polymorphic inlining. - // As a result, if we have a MethodHandle to Object.equals, - // it does not enjoy separate profiles like individual invokevirtuals, - // and we must spin bytecode to accomplish separate profiling. - if (hasPolymorphism) { - String[] names = new String[size]; - - var classFileContext = ClassFile.of(ClassFile.ClassHierarchyResolverOption.of(ClassHierarchyResolver.ofClassLoading(lookup))); - var bytes = classFileContext.build(ClassDesc.of(specializerClassName(lookup.lookupClass(), "Equalator")), clb -> { - for (int i = 0; i < size; i++) { - if (equalators[i] == null) { - var name = "equalator".concat(Integer.toString(i)); - names[i] = name; - var type = getters.get(i).type().returnType(); - boolean isInterface = type.isInterface(); - var typeDesc = type.describeConstable().orElseThrow(); - clb.withMethodBody(name, MethodTypeDesc.of(CD_boolean, typeDesc, typeDesc), ACC_STATIC, cob -> { - var nonNullPath = cob.newLabel(); - var fail = cob.newLabel(); - cob.aload(0) - .ifnonnull(nonNullPath) - .aload(1) - .ifnonnull(fail) - .iconst_1() // arg0 null, arg1 null - .ireturn() - .labelBinding(fail) - .iconst_0() // arg0 null, arg1 non-null - .ireturn() - .labelBinding(nonNullPath) - .aload(0) // arg0.equals(arg1) - bytecode subject to customized profiling - .aload(1) - .invoke(isInterface ? Opcode.INVOKEINTERFACE : Opcode.INVOKEVIRTUAL, typeDesc, "equals", MTD_OBJECT_BOOLEAN, isInterface) - .ireturn(); - }); - } - } - }); - - var specializerLookup = lookup.defineHiddenClass(bytes, true, MethodHandles.Lookup.ClassOption.STRONG); - - for (int i = 0; i < size; i++) { - if (equalators[i] == null) { - var type = getters.get(i).type().returnType(); - equalators[i] = specializerLookup.findStatic(specializerLookup.lookupClass(), names[i], MethodType.methodType(boolean.class, type, type)); - } - } - } - - for (int i = 0; i < size; i++) { - var getter = getters.get(i); - MethodHandle equalator = equalators[i]; // (TT)Z + for (MethodHandle getter : getters) { + MethodHandle equalator = equalator(getter.type().returnType()); // (TT)Z MethodHandle thisFieldEqual = MethodHandles.filterArguments(equalator, 0, getter, getter); // (RR)Z accumulator = MethodHandles.guardWithTest(thisFieldEqual, accumulator, instanceFalse.asType(rr)); } @@ -285,68 +212,13 @@ private static MethodHandle makeEquals(MethodHandles.Lookup lookup, Class rec * @param getters the list of getters * @return the method handle */ - private static MethodHandle makeHashCode(MethodHandles.Lookup lookup, Class receiverClass, - List getters) throws Throwable { + private static MethodHandle makeHashCode(Class receiverClass, + List getters) { MethodHandle accumulator = MethodHandles.dropArguments(ZERO, 0, receiverClass); // (R)I - int size = getters.size(); - MethodHandle[] hashers = new MethodHandle[size]; - boolean hasPolymorphism = false; - for (int i = 0; i < size; i++) { - var getter = getters.get(i); - var type = getter.type().returnType(); - if (isMonomorphic(type)) { - hashers[i] = hasher(lookup, type); - } else { - hasPolymorphism = true; - } - } - - // Currently, hotspot does not support polymorphic inlining. - // As a result, if we have a MethodHandle to Object.hashCode, - // it does not enjoy separate profiles like individual invokevirtuals, - // and we must spin bytecode to accomplish separate profiling. - if (hasPolymorphism) { - String[] names = new String[size]; - - var classFileContext = ClassFile.of(ClassFile.ClassHierarchyResolverOption.of(ClassHierarchyResolver.ofClassLoading(lookup))); - var bytes = classFileContext.build(ClassDesc.of(specializerClassName(lookup.lookupClass(), "Hasher")), clb -> { - for (int i = 0; i < size; i++) { - if (hashers[i] == null) { - var name = "hasher".concat(Integer.toString(i)); - names[i] = name; - var type = getters.get(i).type().returnType(); - boolean isInterface = type.isInterface(); - var typeDesc = type.describeConstable().orElseThrow(); - clb.withMethodBody(name, MethodTypeDesc.of(CD_int, typeDesc), ACC_STATIC, cob -> { - var nonNullPath = cob.newLabel(); - cob.aload(0) - .ifnonnull(nonNullPath) - .iconst_0() // null hash is 0 - .ireturn() - .labelBinding(nonNullPath) - .aload(0) // arg0.hashCode() - bytecode subject to customized profiling - .invoke(isInterface ? Opcode.INVOKEINTERFACE : Opcode.INVOKEVIRTUAL, typeDesc, "hashCode", MTD_INT, isInterface) - .ireturn(); - }); - } - } - }); - - var specializerLookup = lookup.defineHiddenClass(bytes, true, MethodHandles.Lookup.ClassOption.STRONG); - - for (int i = 0; i < size; i++) { - if (hashers[i] == null) { - var type = getters.get(i).type().returnType(); - hashers[i] = specializerLookup.findStatic(specializerLookup.lookupClass(), names[i], MethodType.methodType(int.class, type)); - } - } - } - // @@@ Use loop combinator instead? - for (int i = 0; i < size; i++) { - var getter = getters.get(i); - MethodHandle hasher = hashers[i]; // (T)I + for (MethodHandle getter : getters) { + MethodHandle hasher = hasher(getter.type().returnType()); // (T)I MethodHandle hashThisField = MethodHandles.filterArguments(hasher, 0, getter); // (R)I MethodHandle combineHashes = MethodHandles.filterArguments(HASH_COMBINER, 0, accumulator, hashThisField); // (RR)I accumulator = MethodHandles.permuteArguments(combineHashes, accumulator.type(), 0, 0); // adapt (R)I to (RR)I @@ -531,12 +403,12 @@ public static Object bootstrap(MethodHandles.Lookup lookup, String methodName, T case "equals" -> { if (methodType != null && !methodType.equals(MethodType.methodType(boolean.class, recordClass, Object.class))) throw new IllegalArgumentException("Bad method type: " + methodType); - yield makeEquals(lookup, recordClass, getterList); + yield makeEquals(recordClass, getterList); } case "hashCode" -> { if (methodType != null && !methodType.equals(MethodType.methodType(int.class, recordClass))) throw new IllegalArgumentException("Bad method type: " + methodType); - yield makeHashCode(lookup, recordClass, getterList); + yield makeHashCode(recordClass, getterList); } case "toString" -> { if (methodType != null && !methodType.equals(MethodType.methodType(String.class, recordClass))) diff --git a/src/java.base/share/classes/java/math/BigDecimal.java b/src/java.base/share/classes/java/math/BigDecimal.java index 14d81d30c3d40..c24998344c151 100644 --- a/src/java.base/share/classes/java/math/BigDecimal.java +++ b/src/java.base/share/classes/java/math/BigDecimal.java @@ -154,7 +154,7 @@ * Subtractmax(minuend.scale(), subtrahend.scale()) * Multiplymultiplier.scale() + multiplicand.scale() * Dividedividend.scale() - divisor.scale() - * Square rootceil(radicand.scale()/2.0) + * Square rootradicand.scale()/2 * * * @@ -327,6 +327,10 @@ * @spec https://standards.ieee.org/ieee/754/6210/ * IEEE Standard for Floating-Point Arithmetic * + * @author Josh Bloch + * @author Mike Cowlishaw + * @author Joseph D. Darcy + * @author Sergey V. Kuksenko * @since 1.1 */ public class BigDecimal extends Number implements Comparable { @@ -1775,6 +1779,7 @@ public BigDecimal divide(BigDecimal divisor, RoundingMode roundingMode) { * terminating decimal expansion, including dividing by zero * @return {@code this / divisor} * @since 1.5 + * @author Joseph D. Darcy */ public BigDecimal divide(BigDecimal divisor) { /* @@ -1943,6 +1948,7 @@ public BigDecimal divideToIntegralValue(BigDecimal divisor) { * @throws ArithmeticException if {@code mc.precision} {@literal >} 0 and the result * requires a precision of more than {@code mc.precision} digits. * @since 1.5 + * @author Joseph D. Darcy */ public BigDecimal divideToIntegralValue(BigDecimal divisor, MathContext mc) { if (mc.precision == 0 || // exact result @@ -2113,7 +2119,7 @@ public BigDecimal[] divideAndRemainder(BigDecimal divisor, MathContext mc) { * with rounding according to the context settings. * *

The preferred scale of the returned result is equal to - * {@code Math.ceilDiv(this.scale(), 2)}. The value of the returned result is + * {@code this.scale()/2}. The value of the returned result is * always within one ulp of the exact decimal value for the * precision in question. If the rounding mode is {@link * RoundingMode#HALF_UP HALF_UP}, {@link RoundingMode#HALF_DOWN @@ -2174,7 +2180,7 @@ public BigDecimal sqrt(MathContext mc) { // The code below favors relative simplicity over checking // for special cases that could run faster. - final int preferredScale = Math.ceilDiv(this.scale, 2); + final int preferredScale = this.scale/2; BigDecimal result; if (mc.roundingMode == RoundingMode.UNNECESSARY || mc.precision == 0) { // Exact result requested diff --git a/src/java.base/share/classes/java/math/MathContext.java b/src/java.base/share/classes/java/math/MathContext.java index f80fcc3e076e2..d0c1cb4a5a9ee 100644 --- a/src/java.base/share/classes/java/math/MathContext.java +++ b/src/java.base/share/classes/java/math/MathContext.java @@ -51,6 +51,8 @@ * @spec https://standards.ieee.org/ieee/754/6210/ * IEEE Standard for Floating-Point Arithmetic * + * @author Mike Cowlishaw + * @author Joseph D. Darcy * @since 1.5 */ diff --git a/src/java.base/share/classes/java/math/RoundingMode.java b/src/java.base/share/classes/java/math/RoundingMode.java index 4188c781cab8a..e66a64e143f98 100644 --- a/src/java.base/share/classes/java/math/RoundingMode.java +++ b/src/java.base/share/classes/java/math/RoundingMode.java @@ -115,6 +115,9 @@ * IEEE Standard for Floating-Point Arithmetic * @jls 15.4 Floating-point Expressions * + * @author Josh Bloch + * @author Mike Cowlishaw + * @author Joseph D. Darcy * @since 1.5 */ @SuppressWarnings("deprecation") // Legacy rounding mode constants in BigDecimal diff --git a/src/java.base/share/classes/java/nio/ByteOrder.java b/src/java.base/share/classes/java/nio/ByteOrder.java index ab6876448bea2..96f2317b956d0 100644 --- a/src/java.base/share/classes/java/nio/ByteOrder.java +++ b/src/java.base/share/classes/java/nio/ByteOrder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2023, 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 @@ -35,19 +35,28 @@ * @since 1.4 */ -public enum ByteOrder { - /** - * Constant denoting little-endian byte order. In this order, the bytes of - * a multibyte value are ordered from least significant to most - * significant. - */ - LITTLE_ENDIAN, +public final class ByteOrder { + + private final String name; + + private ByteOrder(String name) { + this.name = name; + } + /** * Constant denoting big-endian byte order. In this order, the bytes of a * multibyte value are ordered from most significant to least significant. */ - BIG_ENDIAN; + public static final ByteOrder BIG_ENDIAN + = new ByteOrder("BIG_ENDIAN"); + /** + * Constant denoting little-endian byte order. In this order, the bytes of + * a multibyte value are ordered from least significant to most + * significant. + */ + public static final ByteOrder LITTLE_ENDIAN + = new ByteOrder("LITTLE_ENDIAN"); // Retrieve the native byte order. It's used early during bootstrap, and // must be initialized after BIG_ENDIAN and LITTLE_ENDIAN. @@ -69,4 +78,18 @@ public enum ByteOrder { public static ByteOrder nativeOrder() { return NATIVE_ORDER; } + + /** + * Constructs a string describing this object. + * + *

This method returns the string + * {@code "BIG_ENDIAN"} for {@link #BIG_ENDIAN} and + * {@code "LITTLE_ENDIAN"} for {@link #LITTLE_ENDIAN}. + * + * @return The specified string + */ + public String toString() { + return name; + } + } diff --git a/src/java.base/share/classes/java/nio/channels/GatheringByteChannel.java b/src/java.base/share/classes/java/nio/channels/GatheringByteChannel.java index e2e97562dee79..4e3b0cf136d2a 100644 --- a/src/java.base/share/classes/java/nio/channels/GatheringByteChannel.java +++ b/src/java.base/share/classes/java/nio/channels/GatheringByteChannel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2023, 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 @@ -76,14 +76,11 @@ public interface GatheringByteChannel * the final position of each updated buffer, except the last updated * buffer, is guaranteed to be equal to that buffer's limit. * - *

For many types of channels, a write operation will return only after + *

Unless otherwise specified, a write operation will return only after * writing all of the r requested bytes. Some types of channels, * depending upon their state, may write only some of the bytes or possibly - * none at all. A socket channel in {@linkplain - * SelectableChannel#isBlocking non-blocking mode}, for example, cannot - * write any more bytes than are free in the socket's output buffer. The - * write method may need to be invoked more than once to ensure that all - * {@linkplain ByteBuffer#hasRemaining remaining} bytes are written. + * none at all. A socket channel in non-blocking mode, for example, cannot + * write any more bytes than are free in the socket's output buffer. * *

This method may be invoked at any time. If another thread has * already initiated a write operation upon this channel, however, then an diff --git a/src/java.base/share/classes/java/nio/channels/WritableByteChannel.java b/src/java.base/share/classes/java/nio/channels/WritableByteChannel.java index 5284c72b37b00..ef8efa5037c42 100644 --- a/src/java.base/share/classes/java/nio/channels/WritableByteChannel.java +++ b/src/java.base/share/classes/java/nio/channels/WritableByteChannel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2005, 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 @@ -65,14 +65,11 @@ public interface WritableByteChannel * Upon return the buffer's position will be equal to * p {@code +} n; its limit will not have changed. * - *

For many types of channels, a write operation will return only after + *

Unless otherwise specified, a write operation will return only after * writing all of the r requested bytes. Some types of channels, * depending upon their state, may write only some of the bytes or possibly - * none at all. A socket channel in {@linkplain - * SelectableChannel#isBlocking non-blocking mode}, for example, cannot - * write any more bytes than are free in the socket's output buffer. The - * write method may need to be invoked more than once to ensure that all - * {@linkplain ByteBuffer#hasRemaining remaining} bytes are written. + * none at all. A socket channel in non-blocking mode, for example, cannot + * write any more bytes than are free in the socket's output buffer. * *

This method may be invoked at any time. If another thread has * already initiated a write operation upon this channel, however, then an diff --git a/src/java.base/share/classes/java/time/Duration.java b/src/java.base/share/classes/java/time/Duration.java index 7b3289a1f5957..23577a8a63495 100644 --- a/src/java.base/share/classes/java/time/Duration.java +++ b/src/java.base/share/classes/java/time/Duration.java @@ -138,37 +138,6 @@ public final class Duration * Constant for a duration of zero. */ public static final Duration ZERO = new Duration(0, 0); - /** - * The minimum supported {@code Duration}, which is {@link Long#MIN_VALUE} - * seconds. - * - * @apiNote This constant represents the smallest possible instance of - * {@code Duration}. Since {@code Duration} is directed, the smallest - * possible duration is negative. - * - * The constant is intended to be used as a sentinel value or in tests. - * Care should be taken when performing arithmetic on {@code MIN} as there - * is a high risk that {@link ArithmeticException} or {@link DateTimeException} - * will be thrown. - * - * @since 26 - */ - public static final Duration MIN = new Duration(Long.MIN_VALUE, 0); - /** - * The maximum supported {@code Duration}, which is {@link Long#MAX_VALUE} - * seconds and {@code 999,999,999} nanoseconds. - * - * @apiNote This constant represents the largest possible instance of - * {@code Duration}. - * - * The constant is intended to be used as a sentinel value or in tests. - * Care should be taken when performing arithmetic on {@code MAX} as there - * is a high risk that {@link ArithmeticException} or {@link DateTimeException} - * will be thrown. - * - * @since 26 - */ - public static final Duration MAX = new Duration(Long.MAX_VALUE, 999_999_999); /** * Serialization version. */ diff --git a/src/java.base/share/classes/java/time/temporal/ChronoUnit.java b/src/java.base/share/classes/java/time/temporal/ChronoUnit.java index 6e944b296daa8..8f94e061d4d48 100644 --- a/src/java.base/share/classes/java/time/temporal/ChronoUnit.java +++ b/src/java.base/share/classes/java/time/temporal/ChronoUnit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, 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 @@ -184,9 +184,10 @@ public enum ChronoUnit implements TemporalUnit { * Artificial unit that represents the concept of forever. * This is primarily used with {@link TemporalField} to represent unbounded fields * such as the year or era. - * The estimated duration of this unit is artificially defined as {@link Duration#MAX}. + * The estimated duration of this unit is artificially defined as the largest duration + * supported by {@link Duration}. */ - FOREVER("Forever", Duration.MAX); + FOREVER("Forever", Duration.ofSeconds(Long.MAX_VALUE, 999_999_999)); private final String name; private final Duration duration; diff --git a/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java b/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java index 1338f2fd8043d..7503c154ddbea 100644 --- a/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java +++ b/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java @@ -1904,8 +1904,8 @@ private Object waitingGet(boolean interruptible) { while ((r = result) == null) { if (q == null) { q = new Signaller(interruptible, 0L, 0L); - if (Thread.currentThread() instanceof ForkJoinWorkerThread wt) - ForkJoinPool.helpAsyncBlocker(wt.pool, q); + if (Thread.currentThread() instanceof ForkJoinWorkerThread) + ForkJoinPool.helpAsyncBlocker(defaultExecutor(), q); } else if (!queued) queued = tryPushStack(q); @@ -1950,8 +1950,8 @@ else if (nanos <= 0L) break; else if (q == null) { q = new Signaller(true, nanos, deadline); - if (Thread.currentThread() instanceof ForkJoinWorkerThread wt) - ForkJoinPool.helpAsyncBlocker(wt.pool, q); + if (Thread.currentThread() instanceof ForkJoinWorkerThread) + ForkJoinPool.helpAsyncBlocker(defaultExecutor(), q); } else if (!queued) queued = tryPushStack(q); diff --git a/src/java.base/share/classes/jdk/internal/math/DoubleConsts.java b/src/java.base/share/classes/jdk/internal/math/DoubleConsts.java index 168e99d4ef5ee..d3a271fdd0709 100644 --- a/src/java.base/share/classes/jdk/internal/math/DoubleConsts.java +++ b/src/java.base/share/classes/jdk/internal/math/DoubleConsts.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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 @@ -32,6 +32,8 @@ /** * This class contains additional constants documenting limits of the * {@code double} type. + * + * @author Joseph D. Darcy */ public class DoubleConsts { diff --git a/src/java.base/share/classes/jdk/internal/math/FloatConsts.java b/src/java.base/share/classes/jdk/internal/math/FloatConsts.java index 2bd484e99f39d..fd304c7871a7d 100644 --- a/src/java.base/share/classes/jdk/internal/math/FloatConsts.java +++ b/src/java.base/share/classes/jdk/internal/math/FloatConsts.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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 @@ -32,6 +32,8 @@ /** * This class contains additional constants documenting limits of the * {@code float} type. + * + * @author Joseph D. Darcy */ public class FloatConsts { diff --git a/src/java.base/share/classes/sun/security/util/DerValue.java b/src/java.base/share/classes/sun/security/util/DerValue.java index ec8b482b07dc3..19e7083180b2e 100644 --- a/src/java.base/share/classes/sun/security/util/DerValue.java +++ b/src/java.base/share/classes/sun/security/util/DerValue.java @@ -859,22 +859,6 @@ public String getUniversalString() throws IOException { return readStringInternal(tag_UniversalString, new UTF_32BE()); } - /** - * Checks that the BMPString does not contain any surrogate characters, - * which are outside the Basic Multilingual Plane. - * - * @throws IOException if illegal characters are detected - */ - public void validateBMPString() throws IOException { - String bmpString = getBMPString(); - for (int i = 0; i < bmpString.length(); i++) { - if (Character.isSurrogate(bmpString.charAt(i))) { - throw new IOException( - "Illegal character in BMPString, index: " + i); - } - } - } - /** * Reads the ASN.1 NULL value */ diff --git a/src/java.base/share/classes/sun/security/x509/AVA.java b/src/java.base/share/classes/sun/security/x509/AVA.java index 214ae71828846..915421c76f2f4 100644 --- a/src/java.base/share/classes/sun/security/x509/AVA.java +++ b/src/java.base/share/classes/sun/security/x509/AVA.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,13 +28,10 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.Reader; -import java.nio.charset.Charset; import java.text.Normalizer; import java.util.*; -import static java.nio.charset.StandardCharsets.ISO_8859_1; import static java.nio.charset.StandardCharsets.UTF_8; -import static java.nio.charset.StandardCharsets.UTF_16BE; import sun.security.util.*; import sun.security.pkcs.PKCS9Attribute; @@ -592,10 +589,6 @@ private static boolean trailingSpace(Reader in) throws IOException { throw new IOException("AVA, extra bytes = " + derval.data.available()); } - - if (value.tag == DerValue.tag_BMPString) { - value.validateBMPString(); - } } AVA(DerInputStream in) throws IOException { @@ -720,8 +713,7 @@ public String toRFC2253String(Map oidMap) { * NOTE: this implementation only emits DirectoryStrings of the * types returned by isDerString(). */ - String valStr = - new String(value.getDataBytes(), getCharset(value, false)); + String valStr = new String(value.getDataBytes(), UTF_8); /* * 2.4 (cont): If the UTF-8 string does not have any of the @@ -840,8 +832,7 @@ public String toRFC2253CanonicalString() { * NOTE: this implementation only emits DirectoryStrings of the * types returned by isDerString(). */ - String valStr = - new String(value.getDataBytes(), getCharset(value, true)); + String valStr = new String(value.getDataBytes(), UTF_8); /* * 2.4 (cont): If the UTF-8 string does not have any of the @@ -936,39 +927,6 @@ private static boolean isDerString(DerValue value, boolean canonical) { } } - /* - * Returns the charset that should be used to decode each DN string type. - * - * This method ensures that multi-byte (UTF8String and BMPString) types - * are decoded using the correct charset and the String forms represent - * the correct characters. For 8-bit ASCII-based types (PrintableString - * and IA5String), we return ISO_8859_1 rather than ASCII, so that the - * complete range of characters can be represented, as many certificates - * do not comply with the Internationalized Domain Name ACE format. - * - * NOTE: this method only supports DirectoryStrings of the types returned - * by isDerString(). - */ - private static Charset getCharset(DerValue value, boolean canonical) { - if (canonical) { - return switch (value.tag) { - case DerValue.tag_PrintableString -> ISO_8859_1; - case DerValue.tag_UTF8String -> UTF_8; - default -> throw new Error("unexpected tag: " + value.tag); - }; - } - - return switch (value.tag) { - case DerValue.tag_PrintableString, - DerValue.tag_T61String, - DerValue.tag_IA5String, - DerValue.tag_GeneralString -> ISO_8859_1; - case DerValue.tag_BMPString -> UTF_16BE; - case DerValue.tag_UTF8String -> UTF_8; - default -> throw new Error("unexpected tag: " + value.tag); - }; - } - boolean hasRFC2253Keyword() { return AVAKeyword.hasKeyword(oid, RFC2253); } diff --git a/src/java.base/share/classes/sun/security/x509/AlgorithmId.java b/src/java.base/share/classes/sun/security/x509/AlgorithmId.java index 8d2c761a011cf..7d525a9add7bf 100644 --- a/src/java.base/share/classes/sun/security/x509/AlgorithmId.java +++ b/src/java.base/share/classes/sun/security/x509/AlgorithmId.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -127,35 +127,10 @@ public AlgorithmId(ObjectIdentifier oid, AlgorithmParameters algparams) { public AlgorithmId(ObjectIdentifier oid, DerValue params) throws IOException { this.algid = oid; - - if (params == null) { - this.encodedParams = null; - this.algParams = null; - return; - } - - /* - * If the parameters field explicitly contains an ASN.1 NULL, treat it as - * "no parameters" rather than storing a literal NULL encoding. - * - * This canonicalization ensures consistent encoding/decoding behavior: - * - Algorithms that omit parameters and those that encode explicit NULL - * are treated equivalently (encodedParams == null). - */ - if (params.tag == DerValue.tag_Null) { - if (params.length() != 0) { - throw new IOException("Invalid ASN.1 NULL in AlgorithmId parameters: " + - "non-zero length"); - } - // Canonicalize to "no parameters" representation for consistency - this.encodedParams = null; - this.algParams = null; - return; + if (params != null) { + encodedParams = params.toByteArray(); + decodeParams(); } - - // Normal case: non-NULL params -> store and decode - this.encodedParams = params.toByteArray(); - decodeParams(); } protected void decodeParams() throws IOException { @@ -188,10 +163,38 @@ public void encode(DerOutputStream out) { bytes.putOID(algid); if (encodedParams == null) { - if (OIDS_REQUIRING_NULL.contains(algid.toString())) { + // MessageDigest algorithms usually have a NULL parameters even + // if most RFCs suggested absent. + // RSA key and signature algorithms requires the NULL parameters + // to be present, see A.1 and A.2.4 of RFC 8017. + if (algid.equals(RSAEncryption_oid) + || algid.equals(MD2_oid) + || algid.equals(MD5_oid) + || algid.equals(SHA_oid) + || algid.equals(SHA224_oid) + || algid.equals(SHA256_oid) + || algid.equals(SHA384_oid) + || algid.equals(SHA512_oid) + || algid.equals(SHA512_224_oid) + || algid.equals(SHA512_256_oid) + || algid.equals(SHA3_224_oid) + || algid.equals(SHA3_256_oid) + || algid.equals(SHA3_384_oid) + || algid.equals(SHA3_512_oid) + || algid.equals(SHA1withRSA_oid) + || algid.equals(SHA224withRSA_oid) + || algid.equals(SHA256withRSA_oid) + || algid.equals(SHA384withRSA_oid) + || algid.equals(SHA512withRSA_oid) + || algid.equals(SHA512$224withRSA_oid) + || algid.equals(SHA512$256withRSA_oid) + || algid.equals(MD2withRSA_oid) + || algid.equals(MD5withRSA_oid) + || algid.equals(SHA3_224withRSA_oid) + || algid.equals(SHA3_256withRSA_oid) + || algid.equals(SHA3_384withRSA_oid) + || algid.equals(SHA3_512withRSA_oid)) { bytes.putNull(); - } else { - // Parameters omitted } } else { bytes.writeBytes(encodedParams); @@ -643,54 +646,30 @@ private static ConcurrentHashMap collectOIDAliases() { public static final ObjectIdentifier MGF1_oid = ObjectIdentifier.of(KnownOIDs.MGF1); - /* Set of OIDs that must explicitly encode a NULL parameter in AlgorithmIdentifier. - * References: - - RFC 8017 (PKCS #1) §A.1, §A.2.4: RSA key and signature algorithms - - RFC 9879 (HMAC) §4: HMAC algorithm identifiers - - RFC 9688 (HMAC with SHA-3) §4.3: HMAC-SHA3 algorithms MUST omit parameters - */ - private static final Set OIDS_REQUIRING_NULL = Set.of( - // MessageDigest algorithms usually have a NULL parameters even - // if most RFCs suggested absent. - KnownOIDs.MD2.value(), - KnownOIDs.MD5.value(), - KnownOIDs.SHA_1.value(), - KnownOIDs.SHA_224.value(), - KnownOIDs.SHA_256.value(), - KnownOIDs.SHA_384.value(), - KnownOIDs.SHA_512.value(), - KnownOIDs.SHA_512$224.value(), - KnownOIDs.SHA_512$256.value(), - KnownOIDs.SHA3_224.value(), - KnownOIDs.SHA3_256.value(), - KnownOIDs.SHA3_384.value(), - KnownOIDs.SHA3_512.value(), - - //--- RSA key and signature algorithms (RFC 8017 §A.1, §A.2.4) - KnownOIDs.RSA.value(), - KnownOIDs.SHA1withRSA.value(), - KnownOIDs.SHA224withRSA.value(), - KnownOIDs.SHA256withRSA.value(), - KnownOIDs.SHA384withRSA.value(), - KnownOIDs.SHA512withRSA.value(), - KnownOIDs.SHA512$224withRSA.value(), - KnownOIDs.SHA512$256withRSA.value(), - KnownOIDs.MD2withRSA.value(), - KnownOIDs.MD5withRSA.value(), - KnownOIDs.SHA3_224withRSA.value(), - KnownOIDs.SHA3_256withRSA.value(), - KnownOIDs.SHA3_384withRSA.value(), - KnownOIDs.SHA3_512withRSA.value(), - - // HMACs per RFC 9879 (Section 4): these require explicit NULL parameters - // Note: HMAC-SHA3 algorithms (RFC 9688 §4.3) MUST omit parameters, - // so they are intentionally excluded from this list. - KnownOIDs.HmacSHA1.value(), - KnownOIDs.HmacSHA224.value(), - KnownOIDs.HmacSHA256.value(), - KnownOIDs.HmacSHA384.value(), - KnownOIDs.HmacSHA512.value(), - KnownOIDs.HmacSHA512$224.value(), - KnownOIDs.HmacSHA512$256.value() - ); + public static final ObjectIdentifier SHA1withRSA_oid = + ObjectIdentifier.of(KnownOIDs.SHA1withRSA); + public static final ObjectIdentifier SHA224withRSA_oid = + ObjectIdentifier.of(KnownOIDs.SHA224withRSA); + public static final ObjectIdentifier SHA256withRSA_oid = + ObjectIdentifier.of(KnownOIDs.SHA256withRSA); + public static final ObjectIdentifier SHA384withRSA_oid = + ObjectIdentifier.of(KnownOIDs.SHA384withRSA); + public static final ObjectIdentifier SHA512withRSA_oid = + ObjectIdentifier.of(KnownOIDs.SHA512withRSA); + public static final ObjectIdentifier SHA512$224withRSA_oid = + ObjectIdentifier.of(KnownOIDs.SHA512$224withRSA); + public static final ObjectIdentifier SHA512$256withRSA_oid = + ObjectIdentifier.of(KnownOIDs.SHA512$256withRSA); + public static final ObjectIdentifier MD2withRSA_oid = + ObjectIdentifier.of(KnownOIDs.MD2withRSA); + public static final ObjectIdentifier MD5withRSA_oid = + ObjectIdentifier.of(KnownOIDs.MD5withRSA); + public static final ObjectIdentifier SHA3_224withRSA_oid = + ObjectIdentifier.of(KnownOIDs.SHA3_224withRSA); + public static final ObjectIdentifier SHA3_256withRSA_oid = + ObjectIdentifier.of(KnownOIDs.SHA3_256withRSA); + public static final ObjectIdentifier SHA3_384withRSA_oid = + ObjectIdentifier.of(KnownOIDs.SHA3_384withRSA); + public static final ObjectIdentifier SHA3_512withRSA_oid = + ObjectIdentifier.of(KnownOIDs.SHA3_512withRSA); } diff --git a/src/java.base/share/legal/aes.md b/src/java.base/share/legal/aes.md new file mode 100644 index 0000000000000..6d0ee2e2bb4a5 --- /dev/null +++ b/src/java.base/share/legal/aes.md @@ -0,0 +1,36 @@ +## Cryptix AES v3.2.0 + +### Cryptix General License +

+
+Cryptix General License
+
+Copyright (c) 1995-2005 The Cryptix Foundation Limited.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+  1. Redistributions of source code must retain the copyright notice,
+     this list of conditions and the following disclaimer.
+
+  2. Redistributions in binary form must reproduce the above copyright
+     notice, this list of conditions and the following disclaimer in
+     the documentation and/or other materials provided with the
+     distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE CRYPTIX FOUNDATION LIMITED AND
+CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE CRYPTIX FOUNDATION LIMITED OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
diff --git a/src/java.base/share/native/libverify/check_code.c b/src/java.base/share/native/libverify/check_code.c index 32df102dcb3a9..7266ac8f93c26 100644 --- a/src/java.base/share/native/libverify/check_code.c +++ b/src/java.base/share/native/libverify/check_code.c @@ -395,8 +395,7 @@ static jboolean is_superclass(context_type *, fullinfo_type); static void initialize_exception_table(context_type *); static int instruction_length(unsigned char *iptr, unsigned char *end); -static jboolean isLegalOffset(context_type *, int bci, int offset); -static jboolean isLegalTarget(context_type *, int target); +static jboolean isLegalTarget(context_type *, int offset); static void verify_constant_pool_type(context_type *, int, unsigned); static void initialize_dataflow(context_type *); @@ -1155,9 +1154,9 @@ verify_opcode_operands(context_type *context, unsigned int inumber, int offset) case JVM_OPC_goto: { /* Set the ->operand to be the instruction number of the target. */ int jump = (((signed char)(code[offset+1])) << 8) + code[offset+2]; - if (!isLegalOffset(context, offset, jump)) - CCerror(context, "Illegal target of jump or branch"); int target = offset + jump; + if (!isLegalTarget(context, target)) + CCerror(context, "Illegal target of jump or branch"); this_idata->operand.i = code_data[target]; break; } @@ -1171,9 +1170,9 @@ verify_opcode_operands(context_type *context, unsigned int inumber, int offset) int jump = (((signed char)(code[offset+1])) << 24) + (code[offset+2] << 16) + (code[offset+3] << 8) + (code[offset + 4]); - if (!isLegalOffset(context, offset, jump)) - CCerror(context, "Illegal target of jump or branch"); int target = offset + jump; + if (!isLegalTarget(context, target)) + CCerror(context, "Illegal target of jump or branch"); this_idata->operand.i = code_data[target]; break; } @@ -1212,16 +1211,13 @@ verify_opcode_operands(context_type *context, unsigned int inumber, int offset) } } saved_operand = NEW(int, keys + 2); - int jump = _ck_ntohl(lpc[0]); - if (!isLegalOffset(context, offset, jump)) + if (!isLegalTarget(context, offset + _ck_ntohl(lpc[0]))) CCerror(context, "Illegal default target in switch"); - int target = offset + jump; - saved_operand[keys + 1] = code_data[target]; + saved_operand[keys + 1] = code_data[offset + _ck_ntohl(lpc[0])]; for (k = keys, lptr = &lpc[3]; --k >= 0; lptr += delta) { - jump = _ck_ntohl(lptr[0]); - if (!isLegalOffset(context, offset, jump)) + int target = offset + _ck_ntohl(lptr[0]); + if (!isLegalTarget(context, target)) CCerror(context, "Illegal branch in tableswitch"); - target = offset + jump; saved_operand[k + 1] = code_data[target]; } saved_operand[0] = keys + 1; /* number of successors */ @@ -1750,24 +1746,11 @@ static int instruction_length(unsigned char *iptr, unsigned char *end) /* Given the target of a branch, make sure that it's a legal target. */ static jboolean -isLegalTarget(context_type *context, int target) -{ - int code_length = context->code_length; - int *code_data = context->code_data; - return (target >= 0 && target < code_length && code_data[target] >= 0); -} - -/* Given a bci and offset, make sure the offset is valid and the target is legal */ -static jboolean -isLegalOffset(context_type *context, int bci, int offset) +isLegalTarget(context_type *context, int offset) { int code_length = context->code_length; int *code_data = context->code_data; - int max_offset = 65535; // JVMS 4.11 - int min_offset = -65535; - if (offset < min_offset || offset > max_offset) return JNI_FALSE; - int target = bci + offset; - return (target >= 0 && target < code_length && code_data[target] >= 0); + return (offset >= 0 && offset < code_length && code_data[offset] >= 0); } diff --git a/src/java.base/windows/classes/java/lang/ProcessImpl.java b/src/java.base/windows/classes/java/lang/ProcessImpl.java index 78180cce678a7..7f7c1e75013c0 100644 --- a/src/java.base/windows/classes/java/lang/ProcessImpl.java +++ b/src/java.base/windows/classes/java/lang/ProcessImpl.java @@ -199,6 +199,7 @@ private static String[] getTokensFromCommand(String command) { } private static final int VERIFICATION_CMD_BAT = 0; + private static final int VERIFICATION_WIN32 = 1; private static final int VERIFICATION_WIN32_SAFE = 2; // inside quotes not allowed private static final int VERIFICATION_LEGACY = 3; // See Command shell overview for documentation of special characters. @@ -383,6 +384,12 @@ private boolean isExe(String executablePath) { return (upName.endsWith(".EXE") || upName.indexOf('.') < 0); } + // Old version that can be bypassed + private boolean isShellFile(String executablePath) { + String upPath = executablePath.toUpperCase(Locale.ROOT); + return (upPath.endsWith(".CMD") || upPath.endsWith(".BAT")); + } + private String quoteString(String arg) { StringBuilder argbuf = new StringBuilder(arg.length() + 2); return argbuf.append('"').append(arg).append('"').toString(); @@ -465,10 +472,12 @@ private ProcessImpl(String cmd[], // Quotation protects from interpretation of the [path] argument as // start of longer path with spaces. Quotation has no influence to // [.exe] extension heuristic. - boolean isShell = !isExe(executablePath); + boolean isShell = allowAmbiguousCommands ? isShellFile(executablePath) + : !isExe(executablePath); cmdstr = createCommandLine( // We need the extended verification procedures - isShell ? VERIFICATION_CMD_BAT : VERIFICATION_WIN32_SAFE, + isShell ? VERIFICATION_CMD_BAT + : (allowAmbiguousCommands ? VERIFICATION_WIN32 : VERIFICATION_WIN32_SAFE), quoteString(executablePath), cmd); } diff --git a/src/java.desktop/share/classes/java/awt/GridBagConstraints.java b/src/java.desktop/share/classes/java/awt/GridBagConstraints.java index 0008f5ac7807d..30f8bc4bf50a1 100644 --- a/src/java.desktop/share/classes/java/awt/GridBagConstraints.java +++ b/src/java.desktop/share/classes/java/awt/GridBagConstraints.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2021, 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 @@ -575,7 +575,7 @@ public class GridBagConstraints implements Cloneable, java.io.Serializable { private static final long serialVersionUID = -1000070633030801713L; /** - * Creates a {@code GridBagConstraints} object with + * Creates a {@code GridBagConstraint} object with * all of its fields set to their default value. */ public GridBagConstraints () { diff --git a/src/java.desktop/share/classes/java/awt/font/NumericShaper.java b/src/java.desktop/share/classes/java/awt/font/NumericShaper.java index 99b59cc2e0ec3..ae50703611264 100644 --- a/src/java.desktop/share/classes/java/awt/font/NumericShaper.java +++ b/src/java.desktop/share/classes/java/awt/font/NumericShaper.java @@ -346,19 +346,6 @@ private static Range indexToRange(int index) { return index < NUM_KEYS ? Range.values()[index] : null; } - private static int toRangeHash(Set ranges) { - int m = 0; - for (Range range : ranges) { - int index = range.ordinal(); - if (index < NUM_KEYS) { - m |= 1 << index; - } else { - m |= (1 << NUM_KEYS) + index; - } - } - return m; - } - private static int toRangeMask(Set ranges) { int m = 0; for (Range range : ranges) { @@ -589,7 +576,7 @@ private boolean inRange(int c) { // and a linear probe is ok. private static int ctCache = 0; - private static final int ctCacheLimit = contexts.length - 2; + private static int ctCacheLimit = contexts.length - 2; // warning, synchronize access to this as it modifies state private static int getContextKey(char c) { @@ -1523,9 +1510,6 @@ public static NumericShaper getContextualShaper(Set ranges, private NumericShaper(int key, int mask) { this.key = key; this.mask = mask; - if (((this.mask & ARABIC) != 0) && ((this.mask & EASTERN_ARABIC) != 0)) { - this.mask &= ~ARABIC; - } } private NumericShaper(Range defaultContext, Set ranges) { @@ -1811,7 +1795,15 @@ private void shapeContextually(char[] text, int start, int count, Range ctxKey) * @see java.lang.Object#hashCode */ public int hashCode() { - return (rangeSet != null) ? Range.toRangeHash(rangeSet) : (mask & ~CONTEXTUAL_MASK); + int hash = mask; + if (rangeSet != null) { + // Use the CONTEXTUAL_MASK bit only for the enum-based + // NumericShaper. A deserialized NumericShaper might have + // bit masks. + hash &= CONTEXTUAL_MASK; + hash ^= rangeSet.hashCode(); + } + return hash; } /** diff --git a/src/java.desktop/share/classes/java/awt/image/BandedSampleModel.java b/src/java.desktop/share/classes/java/awt/image/BandedSampleModel.java index bad9abc61308a..bd955e35870ae 100644 --- a/src/java.desktop/share/classes/java/awt/image/BandedSampleModel.java +++ b/src/java.desktop/share/classes/java/awt/image/BandedSampleModel.java @@ -141,9 +141,12 @@ public BandedSampleModel(int dataType, * @param h the height of the resulting {@code BandedSampleModel} * @return a new {@code BandedSampleModel} with the specified * width and height. - * @throws IllegalArgumentException if the product of {@code w} - * and {@code h} is greater than {@code Integer.MAX_VALUE} - * or {@code w} or {@code h} is not greater than 0. + * @throws IllegalArgumentException if {@code w} or + * {@code h} equals either + * {@code Integer.MAX_VALUE} or + * {@code Integer.MIN_VALUE} + * @throws IllegalArgumentException if {@code dataType} is not + * one of the supported data types */ public SampleModel createCompatibleSampleModel(int w, int h) { int[] bandOffs; @@ -169,8 +172,8 @@ public SampleModel createCompatibleSampleModel(int w, int h) { * of the original BandedSampleModel/DataBuffer combination. * @throws RasterFormatException if the number of bands is greater than * the number of banks in this sample model. - * @throws IllegalArgumentException if the number of bands is not greater than 0 - * @throws ArrayIndexOutOfBoundsException if any of the bank indices is out of bounds + * @throws IllegalArgumentException if {@code dataType} is not + * one of the supported data types */ public SampleModel createSubsetSampleModel(int[] bands) { if (bands.length > bankIndices.length) diff --git a/src/java.desktop/share/classes/java/awt/image/renderable/ContextualRenderedImageFactory.java b/src/java.desktop/share/classes/java/awt/image/renderable/ContextualRenderedImageFactory.java index 8df3895a0216a..94a2aa14bf5b2 100644 --- a/src/java.desktop/share/classes/java/awt/image/renderable/ContextualRenderedImageFactory.java +++ b/src/java.desktop/share/classes/java/awt/image/renderable/ContextualRenderedImageFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2008, 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 @@ -41,7 +41,7 @@ * ContextualRenderedImageFactory provides an interface for the * functionality that may differ between instances of * RenderableImageOp. Thus different operations on RenderableImages - * may be performed by a single class such as RenderableImageOp through + * may be performed by a single class such as RenderedImageOp through * the use of multiple instances of ContextualRenderedImageFactory. * The name ContextualRenderedImageFactory is commonly shortened to * "CRIF." diff --git a/src/java.desktop/share/classes/java/awt/image/renderable/RenderableImageOp.java b/src/java.desktop/share/classes/java/awt/image/renderable/RenderableImageOp.java index f2f0d458ba1c5..19bf3b3932334 100644 --- a/src/java.desktop/share/classes/java/awt/image/renderable/RenderableImageOp.java +++ b/src/java.desktop/share/classes/java/awt/image/renderable/RenderableImageOp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2014, 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 @@ -58,7 +58,7 @@ public class RenderableImageOp implements RenderableImage { /** - * Constructs a {@code RenderableImageOp} given a + * Constructs a RenderedImageOp given a * ContextualRenderedImageFactory object, and * a ParameterBlock containing RenderableImage sources and other * parameters. Any RenderedImage sources referenced by the diff --git a/src/java.desktop/share/classes/javax/swing/ScrollPaneLayout.java b/src/java.desktop/share/classes/javax/swing/ScrollPaneLayout.java index 50cb25fe4f828..0b8d8576f1469 100644 --- a/src/java.desktop/share/classes/javax/swing/ScrollPaneLayout.java +++ b/src/java.desktop/share/classes/javax/swing/ScrollPaneLayout.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,8 +38,8 @@ /** - * The layout manager used by {@code JScrollPane}. - * {@code ScrollPaneLayout} is + * The layout manager used by JScrollPane. + * JScrollPaneLayout is * responsible for nine components: a viewport, two scrollbars, * a row header, a column header, and four "corner" components. *

diff --git a/src/java.desktop/share/classes/sun/java2d/marlin/Curve.java b/src/java.desktop/share/classes/sun/java2d/marlin/Curve.java index 9d2c8dc2a72aa..2ce0cd4672cd3 100644 --- a/src/java.desktop/share/classes/sun/java2d/marlin/Curve.java +++ b/src/java.desktop/share/classes/sun/java2d/marlin/Curve.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2021, 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 @@ -144,9 +144,7 @@ int yPoints(final double[] ts, final int off, final double y) // finds points where the first and second derivative are // perpendicular. This happens when g(t) = f'(t)*f''(t) == 0 (where // * is a dot product). Unfortunately, we have to solve a cubic. - private int perpendiculardfddf(final double[] pts, final int off, - final double A, final double B) - { + private int perpendiculardfddf(final double[] pts, final int off) { assert pts.length >= off + 4; // these are the coefficients of some multiple of g(t) (not g(t), @@ -157,7 +155,7 @@ private int perpendiculardfddf(final double[] pts, final int off, final double c = 2.0d * (dax * cx + day * cy) + dbx * dbx + dby * dby; final double d = dbx * cx + dby * cy; - return Helpers.cubicRootsInAB(a, b, c, d, pts, off, A, B); + return Helpers.cubicRootsInAB(a, b, c, d, pts, off, 0.0d, 1.0d); } // Tries to find the roots of the function ROC(t)-w in [0, 1). It uses @@ -173,43 +171,35 @@ private int perpendiculardfddf(final double[] pts, final int off, // at most 4 sub-intervals of (0,1). ROC has asymptotes at inflection // points, so roc-w can have at least 6 roots. This shouldn't be a // problem for what we're trying to do (draw a nice looking curve). - int rootsOfROCMinusW(final double[] roots, final int off, final double w2, - final double A, final double B) - { + int rootsOfROCMinusW(final double[] roots, final int off, final double w2, final double err) { // no OOB exception, because by now off<=6, and roots.length >= 10 assert off <= 6 && roots.length >= 10; int ret = off; - final int end = off + perpendiculardfddf(roots, off, A, B); - Helpers.isort(roots, off, end); + final int end = off + perpendiculardfddf(roots, off); roots[end] = 1.0d; // always check interval end points - double t0 = 0.0d; - double ft0 = eliminateInf(ROCsq(t0) - w2); - double t1, ft1; + double t0 = 0.0d, ft0 = ROCsq(t0) - w2; for (int i = off; i <= end; i++) { - t1 = roots[i]; - ft1 = eliminateInf(ROCsq(t1) - w2); + double t1 = roots[i], ft1 = ROCsq(t1) - w2; if (ft0 == 0.0d) { roots[ret++] = t0; } else if (ft1 * ft0 < 0.0d) { // have opposite signs // (ROC(t)^2 == w^2) == (ROC(t) == w) is true because // ROC(t) >= 0 for all t. - roots[ret++] = falsePositionROCsqMinusX(t0, t1, ft0, ft1, w2, A); // A = err + roots[ret++] = falsePositionROCsqMinusX(t0, t1, w2, err); } t0 = t1; ft0 = ft1; } + return ret - off; } - private final static double MAX_ROC_SQ = 1e20; - - private static double eliminateInf(final double x2) { - // limit the value of x to avoid numerical problems (smaller step): - // must handle NaN and +Infinity: - return (x2 <= MAX_ROC_SQ) ? x2 : MAX_ROC_SQ; + private static double eliminateInf(final double x) { + return (x == Double.POSITIVE_INFINITY ? Double.MAX_VALUE : + (x == Double.NEGATIVE_INFINITY ? Double.MIN_VALUE : x)); } // A slight modification of the false position algorithm on wikipedia. @@ -220,18 +210,17 @@ private static double eliminateInf(final double x2) { // and turn out. Same goes for the newton's method // algorithm in Helpers.java private double falsePositionROCsqMinusX(final double t0, final double t1, - final double ft0, final double ft1, final double w2, final double err) { final int iterLimit = 100; int side = 0; - double s = t0, fs = eliminateInf(ft0); - double t = t1, ft = eliminateInf(ft1); + double t = t1, ft = eliminateInf(ROCsq(t) - w2); + double s = t0, fs = eliminateInf(ROCsq(s) - w2); double r = s, fr; - for (int i = 0; i < iterLimit && Math.abs(t - s) > err; i++) { + for (int i = 0; i < iterLimit && Math.abs(t - s) > err * Math.abs(t + s); i++) { r = (fs * t - ft * s) / (fs - ft); - fr = eliminateInf(ROCsq(r) - w2); + fr = ROCsq(r) - w2; if (sameSign(fr, ft)) { ft = fr; t = r; if (side < 0) { @@ -252,7 +241,7 @@ private double falsePositionROCsqMinusX(final double t0, final double t1, break; } } - return (Math.abs(ft) <= Math.abs(fs)) ? t : s; + return r; } private static boolean sameSign(final double x, final double y) { @@ -267,9 +256,9 @@ private double ROCsq(final double t) { final double dy = t * (t * day + dby) + cy; final double ddx = 2.0d * dax * t + dbx; final double ddy = 2.0d * day * t + dby; - final double dx2dy2 = dx * dx + dy * dy; // positive - final double dxddyddxdy = dx * ddy - dy * ddx; - // may return +Infinity if dxddyddxdy = 0 or NaN if 0/0: - return (dx2dy2 * dx2dy2 * dx2dy2) / (dxddyddxdy * dxddyddxdy); // both positive + final double dx2dy2 = dx * dx + dy * dy; + final double ddx2ddy2 = ddx * ddx + ddy * ddy; + final double ddxdxddydy = ddx * dx + ddy * dy; + return dx2dy2 * ((dx2dy2 * dx2dy2) / (dx2dy2 * ddx2ddy2 - ddxdxddydy * ddxdxddydy)); } } diff --git a/src/java.desktop/share/classes/sun/java2d/marlin/DMarlinRenderingEngine.java b/src/java.desktop/share/classes/sun/java2d/marlin/DMarlinRenderingEngine.java index f829872a8a843..66eb9334e8630 100644 --- a/src/java.desktop/share/classes/sun/java2d/marlin/DMarlinRenderingEngine.java +++ b/src/java.desktop/share/classes/sun/java2d/marlin/DMarlinRenderingEngine.java @@ -564,7 +564,7 @@ void strokeTo(final RendererContext rdrCtx, } private static boolean nearZero(final double num) { - return Math.abs(num) < 2.0d * Helpers.ulp(num); + return Math.abs(num) < 2.0d * Math.ulp(num); } abstract static class NormalizingPathIterator implements PathIterator { diff --git a/src/java.desktop/share/classes/sun/java2d/marlin/Helpers.java b/src/java.desktop/share/classes/sun/java2d/marlin/Helpers.java index 926533cdb2bd6..0aed05ab506fb 100644 --- a/src/java.desktop/share/classes/sun/java2d/marlin/Helpers.java +++ b/src/java.desktop/share/classes/sun/java2d/marlin/Helpers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,19 +31,12 @@ final class Helpers implements MarlinConst { - private final static double T_ERR = 1e-4; - private final static double T_A = T_ERR; - private final static double T_B = 1.0 - T_ERR; - private static final double EPS = 1e-9d; private Helpers() { throw new Error("This is a non instantiable class"); } - /** use lower precision like former Pisces and Marlin (float-precision) */ - static double ulp(final double value) { return Math.ulp((float)value); } - static boolean within(final double x, final double y) { return within(x, y, EPS); } @@ -329,10 +322,10 @@ static int findSubdivPoints(final Curve c, final double[] pts, // now we must subdivide at points where one of the offset curves will have // a cusp. This happens at ts where the radius of curvature is equal to w. - ret += c.rootsOfROCMinusW(ts, ret, w2, T_A, T_B); + ret += c.rootsOfROCMinusW(ts, ret, w2, 0.0001d); - ret = filterOutNotInAB(ts, 0, ret, T_A, T_B); - isort(ts, 0, ret); + ret = filterOutNotInAB(ts, 0, ret, 0.0001d, 0.9999d); + isort(ts, ret); return ret; } @@ -361,7 +354,7 @@ static int findClipPoints(final Curve curve, final double[] pts, if ((outCodeOR & OUTCODE_BOTTOM) != 0) { ret += curve.yPoints(ts, ret, clipRect[1]); } - isort(ts, 0, ret); + isort(ts, ret); return ret; } @@ -381,11 +374,11 @@ static void subdivide(final double[] src, } } - static void isort(final double[] a, final int off, final int len) { - for (int i = off + 1, j; i < len; i++) { + static void isort(final double[] a, final int len) { + for (int i = 1, j; i < len; i++) { final double ai = a[i]; j = i - 1; - for (; j >= off && a[j] > ai; j--) { + for (; j >= 0 && a[j] > ai; j--) { a[j + 1] = a[j]; } a[j + 1] = ai; diff --git a/src/java.desktop/share/classes/sun/java2d/marlin/Stroker.java b/src/java.desktop/share/classes/sun/java2d/marlin/Stroker.java index 1c257bc13d972..59f93ed7d6db7 100644 --- a/src/java.desktop/share/classes/sun/java2d/marlin/Stroker.java +++ b/src/java.desktop/share/classes/sun/java2d/marlin/Stroker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2023, 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 @@ -886,8 +886,8 @@ private int computeOffsetCubic(final double[] pts, final int off, // if p1 == p2 && p3 == p4: draw line from p1->p4, unless p1 == p4, // in which case ignore if p1 == p2 - final boolean p1eqp2 = Helpers.withinD(dx1, dy1, 6.0d * Helpers.ulp(y2)); - final boolean p3eqp4 = Helpers.withinD(dx4, dy4, 6.0d * Helpers.ulp(y4)); + final boolean p1eqp2 = Helpers.withinD(dx1, dy1, 6.0d * Math.ulp(y2)); + final boolean p3eqp4 = Helpers.withinD(dx4, dy4, 6.0d * Math.ulp(y4)); if (p1eqp2 && p3eqp4) { return getLineOffsets(x1, y1, x4, y4, leftOff, rightOff); @@ -905,7 +905,7 @@ private int computeOffsetCubic(final double[] pts, final int off, final double l1sq = dx1 * dx1 + dy1 * dy1; final double l4sq = dx4 * dx4 + dy4 * dy4; - if (Helpers.within(dotsq, l1sq * l4sq, 4.0d * Helpers.ulp(dotsq))) { + if (Helpers.within(dotsq, l1sq * l4sq, 4.0d * Math.ulp(dotsq))) { return getLineOffsets(x1, y1, x4, y4, leftOff, rightOff); } @@ -1078,8 +1078,8 @@ private int computeOffsetQuad(final double[] pts, final int off, // equal if they're very close to each other. // if p1 == p2 or p2 == p3: draw line from p1->p3 - final boolean p1eqp2 = Helpers.withinD(dx12, dy12, 6.0d * Helpers.ulp(y2)); - final boolean p2eqp3 = Helpers.withinD(dx23, dy23, 6.0d * Helpers.ulp(y3)); + final boolean p1eqp2 = Helpers.withinD(dx12, dy12, 6.0d * Math.ulp(y2)); + final boolean p2eqp3 = Helpers.withinD(dx23, dy23, 6.0d * Math.ulp(y3)); if (p1eqp2 || p2eqp3) { return getLineOffsets(x1, y1, x3, y3, leftOff, rightOff); @@ -1091,7 +1091,7 @@ private int computeOffsetQuad(final double[] pts, final int off, final double l1sq = dx12 * dx12 + dy12 * dy12; final double l3sq = dx23 * dx23 + dy23 * dy23; - if (Helpers.within(dotsq, l1sq * l3sq, 4.0d * Helpers.ulp(dotsq))) { + if (Helpers.within(dotsq, l1sq * l3sq, 4.0d * Math.ulp(dotsq))) { return getLineOffsets(x1, y1, x3, y3, leftOff, rightOff); } diff --git a/src/java.desktop/share/conf/psfontj2d.properties b/src/java.desktop/share/conf/psfontj2d.properties index 8030a82bc4f9f..9efe88644283e 100644 --- a/src/java.desktop/share/conf/psfontj2d.properties +++ b/src/java.desktop/share/conf/psfontj2d.properties @@ -59,6 +59,7 @@ avantgarde_book_oblique=avantgarde_book_oblique avantgarde_demi_oblique=avantgarde_demi_oblique # itcavantgarde=avantgarde_book +itcavantgarde=avantgarde_book itcavantgarde_demi=avantgarde_demi itcavantgarde_oblique=avantgarde_book_oblique itcavantgarde_demi_oblique=avantgarde_demi_oblique diff --git a/src/java.desktop/share/native/libsplashscreen/splashscreen_gif.c b/src/java.desktop/share/native/libsplashscreen/splashscreen_gif.c index 4f2cfca8dd093..cbdad61f78e83 100644 --- a/src/java.desktop/share/native/libsplashscreen/splashscreen_gif.c +++ b/src/java.desktop/share/native/libsplashscreen/splashscreen_gif.c @@ -279,9 +279,7 @@ SplashDecodeGif(Splash * splash, GifFileType * gif) ImageRect dstRect; rgbquad_t fillColor = 0; // 0 is transparent - if (colorMap && - colorMap->Colors && - transparentColor < 0) { + if (transparentColor < 0) { fillColor= MAKE_QUAD_GIF( colorMap->Colors[gif->SBackGroundColor], 0xff); } diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c b/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c index e5b2dfa6db98d..916880873c63c 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c +++ b/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c @@ -276,7 +276,10 @@ GtkApi* gtk3_load(JNIEnv *env, const char* lib_name) fp_gtk_check_version = dl_symbol("gtk_check_version"); /* GLib */ - fp_glib_check_version = dl_symbol("glib_check_version"); + fp_glib_check_version = dlsym(gtk3_libhandle, "glib_check_version"); + if (!fp_glib_check_version) { + dlerror(); + } fp_g_free = dl_symbol("g_free"); fp_g_object_unref = dl_symbol("g_object_unref"); diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java index 3a2578b3e0bc4..f28ae2a93264b 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxMenuItemUI.java @@ -76,20 +76,19 @@ protected void paintBackground(Graphics g, JMenuItem menuItem, super.paintBackground(g, menuItem, bgColor); } - @Override + /** + * Paint MenuItem. + */ protected void paintMenuItem(Graphics g, JComponent c, Icon checkIcon, Icon arrowIcon, Color background, Color foreground, int defaultTextIconGap) { if (WindowsMenuItemUI.isVistaPainting()) { - WindowsMenuItemUI.paintMenuItem(accessor, g, c, - checkIcon, arrowIcon, - background, foreground, - disabledForeground, - acceleratorSelectionForeground, - acceleratorForeground, - defaultTextIconGap, - menuItem, getPropertyPrefix()); + WindowsMenuItemUI.paintMenuItem(accessor, g, c, checkIcon, + arrowIcon, background, foreground, + disabledForeground, acceleratorSelectionForeground, + acceleratorForeground, defaultTextIconGap, + menuItem, getPropertyPrefix()); return; } super.paintMenuItem(g, c, checkIcon, arrowIcon, background, diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java index 041bdb5adaaf5..a9b09085ad1a6 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuItemUI.java @@ -29,11 +29,16 @@ import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; +import java.awt.Insets; import java.awt.Rectangle; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; +import java.util.Enumeration; +import javax.swing.AbstractButton; +import javax.swing.ButtonGroup; import javax.swing.ButtonModel; +import javax.swing.DefaultButtonModel; import javax.swing.Icon; import javax.swing.JComponent; import javax.swing.JMenu; @@ -127,6 +132,27 @@ public void propertyChange(PropertyChangeEvent e) { menuItem.addPropertyChangeListener(changeListener); } + protected void installDefaults() { + super.installDefaults(); + String prefix = getPropertyPrefix(); + + if (acceleratorSelectionForeground == null || + acceleratorSelectionForeground instanceof UIResource) { + acceleratorSelectionForeground = + UIManager.getColor(prefix + ".acceleratorSelectionForeground"); + } + if (acceleratorForeground == null || + acceleratorForeground instanceof UIResource) { + acceleratorForeground = + UIManager.getColor(prefix + ".acceleratorForeground"); + } + if (disabledForeground == null || + disabledForeground instanceof UIResource) { + disabledForeground = + UIManager.getColor(prefix + ".disabledForeground"); + } + } + /** * {@inheritDoc} */ @@ -139,19 +165,15 @@ protected void uninstallListeners() { changeListener = null; } - @Override protected void paintMenuItem(Graphics g, JComponent c, Icon checkIcon, Icon arrowIcon, Color background, Color foreground, int defaultTextIconGap) { if (WindowsMenuItemUI.isVistaPainting()) { - WindowsMenuItemUI.paintMenuItem(accessor, g, c, - checkIcon, arrowIcon, - background, foreground, - disabledForeground, - acceleratorSelectionForeground, - acceleratorForeground, - defaultTextIconGap, menuItem, + WindowsMenuItemUI.paintMenuItem(accessor, g, c, checkIcon, + arrowIcon, background, foreground, + disabledForeground, acceleratorSelectionForeground, + acceleratorForeground, defaultTextIconGap, menuItem, getPropertyPrefix()); return; } @@ -160,16 +182,12 @@ protected void paintMenuItem(Graphics g, JComponent c, } static void paintMenuItem(WindowsMenuItemUIAccessor accessor, Graphics g, - JComponent c, - Icon checkIcon, Icon arrowIcon, + JComponent c, Icon checkIcon, Icon arrowIcon, Color background, Color foreground, Color disabledForeground, Color acceleratorSelectionForeground, Color acceleratorForeground, - int defaultTextIconGap, JMenuItem menuItem, - String prefix) { - assert c == menuItem : "menuItem passed as 'c' must be the same"; - + int defaultTextIconGap, JMenuItem menuItem, String prefix) { // Save original graphics font and color Font holdf = g.getFont(); Color holdc = g.getColor(); diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java index 130b09227cc20..754b394d4ac11 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java @@ -131,20 +131,18 @@ protected void installDefaults() { hotTrackingOn = (obj instanceof Boolean) ? (Boolean)obj : true; } - @Override + /** + * Paint MenuItem. + */ protected void paintMenuItem(Graphics g, JComponent c, - Icon checkIcon, Icon arrowIcon, - Color background, Color foreground, - int defaultTextIconGap) { - assert c == menuItem : "menuItem passed as 'c' must be the same"; + Icon checkIcon, Icon arrowIcon, + Color background, Color foreground, + int defaultTextIconGap) { if (WindowsMenuItemUI.isVistaPainting()) { - WindowsMenuItemUI.paintMenuItem(accessor, g, c, - checkIcon, arrowIcon, + WindowsMenuItemUI.paintMenuItem(accessor, g, c, checkIcon, arrowIcon, background, foreground, - disabledForeground, - acceleratorSelectionForeground, - acceleratorForeground, - defaultTextIconGap, menuItem, + disabledForeground, acceleratorSelectionForeground, + acceleratorForeground, defaultTextIconGap, menuItem, getPropertyPrefix()); return; } diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java index 78768c29ab3b7..06ef5db23a1b2 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonMenuItemUI.java @@ -76,20 +76,19 @@ protected void paintBackground(Graphics g, JMenuItem menuItem, super.paintBackground(g, menuItem, bgColor); } - @Override + /** + * Paint MenuItem. + */ protected void paintMenuItem(Graphics g, JComponent c, Icon checkIcon, Icon arrowIcon, Color background, Color foreground, int defaultTextIconGap) { if (WindowsMenuItemUI.isVistaPainting()) { - WindowsMenuItemUI.paintMenuItem(accessor, g, c, - checkIcon, arrowIcon, - background, foreground, - disabledForeground, - acceleratorSelectionForeground, - acceleratorForeground, - defaultTextIconGap, - menuItem, getPropertyPrefix()); + WindowsMenuItemUI.paintMenuItem(accessor, g, c, checkIcon, + arrowIcon, background, foreground, + disabledForeground, acceleratorSelectionForeground, + acceleratorForeground, defaultTextIconGap, + menuItem, getPropertyPrefix()); return; } super.paintMenuItem(g, c, checkIcon, arrowIcon, background, diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/Http1Request.java b/src/java.net.http/share/classes/jdk/internal/net/http/Http1Request.java index 8d28b664036c8..815b6bad20c0c 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/Http1Request.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/Http1Request.java @@ -290,8 +290,7 @@ List headers() { } String uriString = requestURI(); StringBuilder sb = new StringBuilder(64); - String method = request.method(); - sb.append(method) + sb.append(request.method()) .append(' ') .append(uriString) .append(" HTTP/1.1\r\n"); @@ -301,15 +300,11 @@ List headers() { systemHeadersBuilder.setHeader("Host", hostString()); } + // GET, HEAD and DELETE with no request body should not set the Content-Length header if (requestPublisher != null) { contentLength = requestPublisher.contentLength(); if (contentLength == 0) { - // PUT and POST with no request body should set the Content-Length header - // even when the content is empty. - // Other methods defined in RFC 9110 should not send the header in that case. - if ("POST".equals(method) || "PUT".equals(method)) { - systemHeadersBuilder.setHeader("Content-Length", "0"); - } + systemHeadersBuilder.setHeader("Content-Length", "0"); } else if (contentLength > 0) { systemHeadersBuilder.setHeader("Content-Length", Long.toString(contentLength)); streaming = false; diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java b/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java index a02506cff5c76..b14d76d8dbadb 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java @@ -174,20 +174,15 @@ private static boolean hostnameVerificationDisabledValue() { public static final int SLICE_THRESHOLD = 32; /** - * The capacity of ephemeral {@link ByteBuffer}s allocated to pass data to and from the client. - * It is ensured to have a value between 1 and 2^14 (16,384). + * Allocated buffer size. Must never be higher than 16K. But can be lower + * if smaller allocation units preferred. HTTP/2 mandates that all + * implementations support frame payloads of at least 16K. */ + private static final int DEFAULT_BUFSIZE = 16 * 1024; + public static final int BUFSIZE = getIntegerNetProperty( - "jdk.httpclient.bufsize", 1, - // We cap at 2^14 (16,384) for two main reasons: - // - The initial frame size is 2^14 (RFC 9113) - // - SSL record layer fragments data in chunks of 2^14 bytes or less (RFC 5246) - 1 << 14, - // We choose 2^14 (16,384) as the default, because: - // 1. It maximizes throughput within the limits described above - // 2. It is small enough to not create a GC bottleneck when it is partially filled - 1 << 14, - true); + "jdk.httpclient.bufsize", DEFAULT_BUFSIZE + ); public static final BiPredicate ACCEPT_ALL = (x,y) -> true; diff --git a/src/java.net.http/share/classes/module-info.java b/src/java.net.http/share/classes/module-info.java index 48f23953ad088..392385136b084 100644 --- a/src/java.net.http/share/classes/module-info.java +++ b/src/java.net.http/share/classes/module-info.java @@ -48,9 +48,7 @@ * depending on the context. These restrictions cannot be overridden by this property. * *

  • {@systemProperty jdk.httpclient.bufsize} (default: 16384 bytes or 16 kB)
    - * The capacity of internal ephemeral buffers allocated to pass data to and from the - * client, in bytes. Valid values are in the range [1, 2^14 (16384)]. - * If an invalid value is provided, the default value is used. + * The size to use for internal allocated buffers in bytes. *

  • *
  • {@systemProperty jdk.httpclient.connectionPoolSize} (default: 0)
    * The maximum number of connections to keep in the HTTP/1.1 keep alive cache. A value of 0 diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderFactoryImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderFactoryImpl.java index bc8e93b4f0b92..385b8e294395d 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderFactoryImpl.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/DocumentBuilderFactoryImpl.java @@ -41,7 +41,7 @@ /** * @author Rajiv Mordani * @author Edwin Goei - * @LastModified: June 2025 + * @LastModified: May 2025 */ public class DocumentBuilderFactoryImpl extends DocumentBuilderFactory { /** These are DocumentBuilderFactory attributes not DOM attributes */ @@ -59,24 +59,11 @@ public class DocumentBuilderFactoryImpl extends DocumentBuilderFactory { XMLSecurityManager fSecurityManager; XMLSecurityPropertyManager fSecurityPropertyMgr; - /** - * Creates a new {@code DocumentBuilderFactory} instance. - */ public DocumentBuilderFactoryImpl() { - this(null, null); - } - - /** - * Creates a new {@code DocumentBuilderFactory} instance with a {@code XMLSecurityManager} - * and {@code XMLSecurityPropertyManager}. - * @param xsm the {@code XMLSecurityManager} - * @param xspm the {@code XMLSecurityPropertyManager} - */ - public DocumentBuilderFactoryImpl(XMLSecurityManager xsm, XMLSecurityPropertyManager xspm) { JdkXmlConfig config = JdkXmlConfig.getInstance(false); // security (property) managers updated with current system properties - fSecurityManager = (xsm == null) ? config.getXMLSecurityManager(true) : xsm; - fSecurityPropertyMgr = (xspm == null) ? config.getXMLSecurityPropertyManager(true) : xspm; + fSecurityManager = config.getXMLSecurityManager(true); + fSecurityPropertyMgr = config.getXMLSecurityPropertyManager(true); } /** diff --git a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathFactoryImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathFactoryImpl.java index 2f4d2ade54530..1288f1dbac32a 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathFactoryImpl.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathFactoryImpl.java @@ -35,7 +35,7 @@ * * @author Ramesh Mandava * - * @LastModified: June 2025 + * @LastModified: May 2025 */ public class XPathFactoryImpl extends XPathFactory { @@ -72,7 +72,6 @@ public class XPathFactoryImpl extends XPathFactory { * The XML security manager */ private XMLSecurityManager _xmlSecMgr; - private XMLSecurityPropertyManager _xmlSecPropMgr; /** * javax.xml.xpath.XPathFactory implementation. @@ -81,7 +80,6 @@ public XPathFactoryImpl() { JdkXmlConfig config = JdkXmlConfig.getInstance(false); _xmlSecMgr = config.getXMLSecurityManager(true); _featureManager = config.getXMLFeatures(true); - _xmlSecPropMgr = config.getXMLSecurityPropertyManager(true); } /** @@ -131,7 +129,7 @@ public boolean isObjectModelSupported(String objectModel) { */ public javax.xml.xpath.XPath newXPath() { return new XPathImpl(xPathVariableResolver, xPathFunctionResolver, - !_isNotSecureProcessing, _featureManager, _xmlSecMgr, _xmlSecPropMgr); + !_isNotSecureProcessing, _featureManager, _xmlSecMgr); } /** @@ -185,7 +183,6 @@ public void setFeature(String name, boolean value) if (value && _featureManager != null) { _featureManager.setFeature(JdkXmlFeatures.XmlFeature.ENABLE_EXTENSION_FUNCTION, JdkProperty.State.FSP, false); - _xmlSecMgr.setSecureProcessing(value); } // all done processing feature @@ -341,7 +338,8 @@ public void setProperty(String name, String value) { throw new NullPointerException(fmsg); } - if (JdkXmlUtils.setProperty(_xmlSecMgr, _xmlSecPropMgr, name, value)) { + if (_xmlSecMgr != null && + _xmlSecMgr.setLimit(name, JdkProperty.State.APIPROPERTY, value)) { return; } diff --git a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImpl.java b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImpl.java index c2faf90ce2e1e..53099ad078ec4 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImpl.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImpl.java @@ -36,7 +36,6 @@ import jdk.xml.internal.JdkXmlConfig; import jdk.xml.internal.JdkXmlFeatures; import jdk.xml.internal.XMLSecurityManager; -import jdk.xml.internal.XMLSecurityPropertyManager; import org.w3c.dom.Document; import org.xml.sax.InputSource; @@ -51,7 +50,7 @@ * New methods: evaluateExpression * Refactored to share code with XPathExpressionImpl. * - * @LastModified: June 2025 + * @LastModified: May 2025 */ public class XPathImpl extends XPathImplUtil implements javax.xml.xpath.XPath { @@ -63,13 +62,12 @@ public class XPathImpl extends XPathImplUtil implements javax.xml.xpath.XPath { XPathImpl(XPathVariableResolver vr, XPathFunctionResolver fr) { this(vr, fr, false, JdkXmlConfig.getInstance(false).getXMLFeatures(false), - JdkXmlConfig.getInstance(false).getXMLSecurityManager(false), - JdkXmlConfig.getInstance(false).getXMLSecurityPropertyManager(false)); + JdkXmlConfig.getInstance(false).getXMLSecurityManager(false)); } XPathImpl(XPathVariableResolver vr, XPathFunctionResolver fr, boolean featureSecureProcessing, JdkXmlFeatures featureManager, - XMLSecurityManager xmlSecMgr, XMLSecurityPropertyManager xmlSecPropMgr) { + XMLSecurityManager xmlSecMgr) { this.origVariableResolver = this.variableResolver = vr; this.origFunctionResolver = this.functionResolver = fr; this.featureSecureProcessing = featureSecureProcessing; @@ -77,7 +75,6 @@ public class XPathImpl extends XPathImplUtil implements javax.xml.xpath.XPath { overrideDefaultParser = featureManager.getFeature( JdkXmlFeatures.XmlFeature.JDK_OVERRIDE_PARSER); this.xmlSecMgr = xmlSecMgr; - this.xmlSecPropMgr = xmlSecPropMgr; } diff --git a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImplUtil.java b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImplUtil.java index 3de72f3f68bb2..a92090900facb 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImplUtil.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/jaxp/XPathImplUtil.java @@ -31,7 +31,6 @@ import com.sun.org.apache.xpath.internal.objects.XObject; import com.sun.org.apache.xpath.internal.res.XPATHErrorResources; import java.io.IOException; -import javax.xml.XMLConstants; import javax.xml.namespace.QName; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; @@ -45,7 +44,6 @@ import jdk.xml.internal.JdkXmlFeatures; import jdk.xml.internal.JdkXmlUtils; import jdk.xml.internal.XMLSecurityManager; -import jdk.xml.internal.XMLSecurityPropertyManager; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.traversal.NodeIterator; @@ -56,7 +54,7 @@ * This class contains several utility methods used by XPathImpl and * XPathExpressionImpl * - * @LastModified: June 2025 + * @LastModified: Apr 2025 */ class XPathImplUtil { XPathFunctionResolver functionResolver; @@ -69,7 +67,6 @@ class XPathImplUtil { boolean featureSecureProcessing = false; JdkXmlFeatures featureManager; XMLSecurityManager xmlSecMgr; - XMLSecurityPropertyManager xmlSecPropMgr; /** * Evaluate an XPath context using the internal XPath engine @@ -131,12 +128,7 @@ Document getDocument(InputSource source) // // so we really have to create a fresh DocumentBuilder every time we need one // - KK - DocumentBuilderFactory dbf = JdkXmlUtils.getDOMFactory( - overrideDefaultParser, xmlSecMgr, xmlSecPropMgr); - if (xmlSecMgr != null && xmlSecMgr.isSecureProcessingSet()) { - dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, - xmlSecMgr.isSecureProcessing()); - } + DocumentBuilderFactory dbf = JdkXmlUtils.getDOMFactory(overrideDefaultParser); return dbf.newDocumentBuilder().parse(source); } catch (ParserConfigurationException | SAXException | IOException e) { throw new XPathExpressionException (e); diff --git a/src/java.xml/share/classes/jdk/xml/internal/JdkXmlUtils.java b/src/java.xml/share/classes/jdk/xml/internal/JdkXmlUtils.java index 9e718b264e447..93b63a746f15e 100644 --- a/src/java.xml/share/classes/jdk/xml/internal/JdkXmlUtils.java +++ b/src/java.xml/share/classes/jdk/xml/internal/JdkXmlUtils.java @@ -445,20 +445,6 @@ public static Document getDOMDocument() { * @return a DocumentBuilderFactory instance. */ public static DocumentBuilderFactory getDOMFactory(boolean overrideDefaultParser) { - return getDOMFactory(overrideDefaultParser, null, null); - } - - /** - * {@return a DocumentBuilderFactory instance} - * - * @param overrideDefaultParser a flag indicating whether the system-default - * implementation may be overridden. If the system property of the - * DOM factory ID is set, override is always allowed. - * @param xsm XMLSecurityManager - * @param xspm XMLSecurityPropertyManager - */ - public static DocumentBuilderFactory getDOMFactory(boolean overrideDefaultParser, - XMLSecurityManager xsm, XMLSecurityPropertyManager xspm) { boolean override = overrideDefaultParser; String spDOMFactory = SecuritySupport.getJAXPSystemProperty(DOM_FACTORY_ID); @@ -467,7 +453,7 @@ public static DocumentBuilderFactory getDOMFactory(boolean overrideDefaultParser } DocumentBuilderFactory dbf = !override - ? new DocumentBuilderFactoryImpl(xsm, xspm) + ? new DocumentBuilderFactoryImpl() : DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); // false is the default setting. This step here is for compatibility diff --git a/src/java.xml/share/classes/jdk/xml/internal/XMLSecurityManager.java b/src/java.xml/share/classes/jdk/xml/internal/XMLSecurityManager.java index a1687c420c3ff..5ca4073e20f2f 100644 --- a/src/java.xml/share/classes/jdk/xml/internal/XMLSecurityManager.java +++ b/src/java.xml/share/classes/jdk/xml/internal/XMLSecurityManager.java @@ -244,12 +244,6 @@ public static enum Processor { */ boolean secureProcessing; - /** - * Flag indicating the secure processing is set explicitly through factories' - * setFeature method and then the setSecureProcessing method - */ - boolean secureProcessingSet; - /** * States that determine if properties are set explicitly */ @@ -346,7 +340,6 @@ private NotFoundAction toActionType(String resolve) { * Setting FEATURE_SECURE_PROCESSING explicitly */ public void setSecureProcessing(boolean secure) { - secureProcessingSet = true; secureProcessing = secure; for (Limit limit : Limit.values()) { if (secure) { @@ -365,15 +358,6 @@ public boolean isSecureProcessing() { return secureProcessing; } - /** - * Returns the state indicating whether the Secure Processing is set explicitly, - * via factories' setFeature and then this class' setSecureProcessing method. - * @return the state indicating whether the Secure Processing is set explicitly - */ - public boolean isSecureProcessingSet() { - return secureProcessingSet; - } - /** * Finds a limit's new name with the given property name. * @param propertyName the property name specified diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java deleted file mode 100644 index 7a8067ce983f8..0000000000000 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/ExhaustivenessComputer.java +++ /dev/null @@ -1,604 +0,0 @@ -/* - * 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 - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * 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 com.sun.tools.javac.comp; - -import java.util.Map; -import java.util.Map.Entry; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Set; -import com.sun.tools.javac.code.*; -import com.sun.tools.javac.tree.*; -import com.sun.tools.javac.util.*; - -import com.sun.tools.javac.code.Symbol.*; -import com.sun.tools.javac.tree.JCTree.*; - -import com.sun.tools.javac.code.Kinds.Kind; -import com.sun.tools.javac.code.Type.TypeVar; -import java.util.Arrays; -import java.util.Iterator; -import java.util.function.Predicate; -import java.util.stream.Collectors; - -import static java.util.stream.Collectors.groupingBy; - -/** A class to compute exhaustiveness of set of switch cases. - * - *

    This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class ExhaustivenessComputer { - protected static final Context.Key exhaustivenessKey = new Context.Key<>(); - - private final Symtab syms; - private final Types types; - private final Check chk; - private final Infer infer; - - public static ExhaustivenessComputer instance(Context context) { - ExhaustivenessComputer instance = context.get(exhaustivenessKey); - if (instance == null) - instance = new ExhaustivenessComputer(context); - return instance; - } - - @SuppressWarnings("this-escape") - protected ExhaustivenessComputer(Context context) { - context.put(exhaustivenessKey, this); - syms = Symtab.instance(context); - types = Types.instance(context); - chk = Check.instance(context); - infer = Infer.instance(context); - } - - public boolean exhausts(JCExpression selector, List cases) { - Set patternSet = new HashSet<>(); - Map> enum2Constants = new HashMap<>(); - Set booleanLiterals = new HashSet<>(Set.of(0, 1)); - for (JCCase c : cases) { - if (!TreeInfo.unguardedCase(c)) - continue; - - for (var l : c.labels) { - if (l instanceof JCPatternCaseLabel patternLabel) { - for (Type component : components(selector.type)) { - patternSet.add(makePatternDescription(component, patternLabel.pat)); - } - } else if (l instanceof JCConstantCaseLabel constantLabel) { - if (types.unboxedTypeOrType(selector.type).hasTag(TypeTag.BOOLEAN)) { - Object value = ((JCLiteral) constantLabel.expr).value; - booleanLiterals.remove(value); - } else { - Symbol s = TreeInfo.symbol(constantLabel.expr); - if (s != null && s.isEnum()) { - enum2Constants.computeIfAbsent(s.owner, x -> { - Set result = new HashSet<>(); - s.owner.members() - .getSymbols(sym -> sym.kind == Kind.VAR && sym.isEnum()) - .forEach(result::add); - return result; - }).remove(s); - } - } - } - } - } - - if (types.unboxedTypeOrType(selector.type).hasTag(TypeTag.BOOLEAN) && booleanLiterals.isEmpty()) { - return true; - } - - for (Entry> e : enum2Constants.entrySet()) { - if (e.getValue().isEmpty()) { - patternSet.add(new BindingPattern(e.getKey().type)); - } - } - Set patterns = patternSet; - boolean useHashes = true; - try { - boolean repeat = true; - while (repeat) { - Set updatedPatterns; - updatedPatterns = reduceBindingPatterns(selector.type, patterns); - updatedPatterns = reduceNestedPatterns(updatedPatterns, useHashes); - updatedPatterns = reduceRecordPatterns(updatedPatterns); - updatedPatterns = removeCoveredRecordPatterns(updatedPatterns); - repeat = !updatedPatterns.equals(patterns); - if (checkCovered(selector.type, patterns)) { - return true; - } - if (!repeat) { - //there may be situation like: - //class B permits S1, S2 - //patterns: R(S1, B), R(S2, S2) - //this might be joined to R(B, S2), as B could be rewritten to S2 - //but hashing in reduceNestedPatterns will not allow that - //disable the use of hashing, and use subtyping in - //reduceNestedPatterns to handle situations like this: - repeat = useHashes; - useHashes = false; - } else { - //if a reduction happened, make sure hashing in reduceNestedPatterns - //is enabled, as the hashing speeds up the process significantly: - useHashes = true; - } - patterns = updatedPatterns; - } - return checkCovered(selector.type, patterns); - } catch (CompletionFailure cf) { - chk.completionError(selector.pos(), cf); - return true; //error recovery - } - } - - private boolean checkCovered(Type seltype, Iterable patterns) { - for (Type seltypeComponent : components(seltype)) { - for (PatternDescription pd : patterns) { - if(isBpCovered(seltypeComponent, pd)) { - return true; - } - } - } - return false; - } - - private List components(Type seltype) { - return switch (seltype.getTag()) { - case CLASS -> { - if (seltype.isCompound()) { - if (seltype.isIntersection()) { - yield ((Type.IntersectionClassType) seltype).getComponents() - .stream() - .flatMap(t -> components(t).stream()) - .collect(List.collector()); - } - yield List.nil(); - } - yield List.of(types.erasure(seltype)); - } - case TYPEVAR -> components(((TypeVar) seltype).getUpperBound()); - default -> List.of(types.erasure(seltype)); - }; - } - - /* In a set of patterns, search for a sub-set of binding patterns that - * in combination exhaust their sealed supertype. If such a sub-set - * is found, it is removed, and replaced with a binding pattern - * for the sealed supertype. - */ - private Set reduceBindingPatterns(Type selectorType, Set patterns) { - Set existingBindings = patterns.stream() - .filter(pd -> pd instanceof BindingPattern) - .map(pd -> ((BindingPattern) pd).type.tsym) - .collect(Collectors.toSet()); - - for (PatternDescription pdOne : patterns) { - if (pdOne instanceof BindingPattern bpOne) { - Set toAdd = new HashSet<>(); - - for (Type sup : types.directSupertypes(bpOne.type)) { - ClassSymbol clazz = (ClassSymbol) types.erasure(sup).tsym; - - clazz.complete(); - - if (clazz.isSealed() && clazz.isAbstract() && - //if a binding pattern for clazz already exists, no need to analyze it again: - !existingBindings.contains(clazz)) { - ListBuffer bindings = new ListBuffer<>(); - //do not reduce to types unrelated to the selector type: - Type clazzErasure = types.erasure(clazz.type); - if (components(selectorType).stream() - .map(types::erasure) - .noneMatch(c -> types.isSubtype(clazzErasure, c))) { - continue; - } - - Set permitted = allPermittedSubTypes(clazz, csym -> { - Type instantiated; - if (csym.type.allparams().isEmpty()) { - instantiated = csym.type; - } else { - instantiated = infer.instantiatePatternType(selectorType, csym); - } - - return instantiated != null && types.isCastable(selectorType, instantiated); - }); - - for (PatternDescription pdOther : patterns) { - if (pdOther instanceof BindingPattern bpOther) { - Set currentPermittedSubTypes = - allPermittedSubTypes(bpOther.type.tsym, s -> true); - - PERMITTED: for (Iterator it = permitted.iterator(); it.hasNext();) { - Symbol perm = it.next(); - - for (Symbol currentPermitted : currentPermittedSubTypes) { - if (types.isSubtype(types.erasure(currentPermitted.type), - types.erasure(perm.type))) { - it.remove(); - continue PERMITTED; - } - } - if (types.isSubtype(types.erasure(perm.type), - types.erasure(bpOther.type))) { - it.remove(); - } - } - } - } - - if (permitted.isEmpty()) { - toAdd.add(new BindingPattern(clazz.type)); - } - } - } - - if (!toAdd.isEmpty()) { - Set newPatterns = new HashSet<>(patterns); - newPatterns.addAll(toAdd); - return newPatterns; - } - } - } - return patterns; - } - - private Set allPermittedSubTypes(TypeSymbol root, Predicate accept) { - Set permitted = new HashSet<>(); - List permittedSubtypesClosure = baseClasses(root); - - while (permittedSubtypesClosure.nonEmpty()) { - ClassSymbol current = permittedSubtypesClosure.head; - - permittedSubtypesClosure = permittedSubtypesClosure.tail; - - current.complete(); - - if (current.isSealed() && current.isAbstract()) { - for (Type t : current.getPermittedSubclasses()) { - ClassSymbol csym = (ClassSymbol) t.tsym; - - if (accept.test(csym)) { - permittedSubtypesClosure = permittedSubtypesClosure.prepend(csym); - permitted.add(csym); - } - } - } - } - - return permitted; - } - - private List baseClasses(TypeSymbol root) { - if (root instanceof ClassSymbol clazz) { - return List.of(clazz); - } else if (root instanceof TypeVariableSymbol tvar) { - ListBuffer result = new ListBuffer<>(); - for (Type bound : tvar.getBounds()) { - result.appendList(baseClasses(bound.tsym)); - } - return result.toList(); - } else { - return List.nil(); - } - } - - /* Among the set of patterns, find sub-set of patterns such: - * $record($prefix$, $nested, $suffix$) - * Where $record, $prefix$ and $suffix$ is the same for each pattern - * in the set, and the patterns only differ in one "column" in - * the $nested pattern. - * Then, the set of $nested patterns is taken, and passed recursively - * to reduceNestedPatterns and to reduceBindingPatterns, to - * simplify the pattern. If that succeeds, the original found sub-set - * of patterns is replaced with a new set of patterns of the form: - * $record($prefix$, $resultOfReduction, $suffix$) - * - * useHashes: when true, patterns will be subject to exact equivalence; - * when false, two binding patterns will be considered equivalent - * if one of them is more generic than the other one; - * when false, the processing will be significantly slower, - * as pattern hashes cannot be used to speed up the matching process - */ - private Set reduceNestedPatterns(Set patterns, - boolean useHashes) { - /* implementation note: - * finding a sub-set of patterns that only differ in a single - * column is time-consuming task, so this method speeds it up by: - * - group the patterns by their record class - * - for each column (nested pattern) do: - * -- group patterns by their hash - * -- in each such by-hash group, find sub-sets that only differ in - * the chosen column, and then call reduceBindingPatterns and reduceNestedPatterns - * on patterns in the chosen column, as described above - */ - var groupByRecordClass = - patterns.stream() - .filter(pd -> pd instanceof RecordPattern) - .map(pd -> (RecordPattern) pd) - .collect(groupingBy(pd -> (ClassSymbol) pd.recordType.tsym)); - - for (var e : groupByRecordClass.entrySet()) { - int nestedPatternsCount = e.getKey().getRecordComponents().size(); - Set current = new HashSet<>(e.getValue()); - - for (int mismatchingCandidate = 0; - mismatchingCandidate < nestedPatternsCount; - mismatchingCandidate++) { - int mismatchingCandidateFin = mismatchingCandidate; - var groupEquivalenceCandidates = - current - .stream() - //error recovery, ignore patterns with incorrect number of nested patterns: - .filter(pd -> pd.nested.length == nestedPatternsCount) - .collect(groupingBy(pd -> useHashes ? pd.hashCode(mismatchingCandidateFin) : 0)); - for (var candidates : groupEquivalenceCandidates.values()) { - var candidatesArr = candidates.toArray(RecordPattern[]::new); - - for (int firstCandidate = 0; - firstCandidate < candidatesArr.length; - firstCandidate++) { - RecordPattern rpOne = candidatesArr[firstCandidate]; - ListBuffer join = new ListBuffer<>(); - - join.append(rpOne); - - NEXT_PATTERN: for (int nextCandidate = 0; - nextCandidate < candidatesArr.length; - nextCandidate++) { - if (firstCandidate == nextCandidate) { - continue; - } - - RecordPattern rpOther = candidatesArr[nextCandidate]; - if (rpOne.recordType.tsym == rpOther.recordType.tsym) { - for (int i = 0; i < rpOne.nested.length; i++) { - if (i != mismatchingCandidate) { - if (!rpOne.nested[i].equals(rpOther.nested[i])) { - if (useHashes || - //when not using hashes, - //check if rpOne.nested[i] is - //a subtype of rpOther.nested[i]: - !(rpOne.nested[i] instanceof BindingPattern bpOne) || - !(rpOther.nested[i] instanceof BindingPattern bpOther) || - !types.isSubtype(types.erasure(bpOne.type), types.erasure(bpOther.type))) { - continue NEXT_PATTERN; - } - } - } - } - join.append(rpOther); - } - } - - var nestedPatterns = join.stream().map(rp -> rp.nested[mismatchingCandidateFin]).collect(Collectors.toSet()); - var updatedPatterns = reduceNestedPatterns(nestedPatterns, useHashes); - - updatedPatterns = reduceRecordPatterns(updatedPatterns); - updatedPatterns = removeCoveredRecordPatterns(updatedPatterns); - updatedPatterns = reduceBindingPatterns(rpOne.fullComponentTypes()[mismatchingCandidateFin], updatedPatterns); - - if (!nestedPatterns.equals(updatedPatterns)) { - if (useHashes) { - current.removeAll(join); - } - - for (PatternDescription nested : updatedPatterns) { - PatternDescription[] newNested = - Arrays.copyOf(rpOne.nested, rpOne.nested.length); - newNested[mismatchingCandidateFin] = nested; - current.add(new RecordPattern(rpOne.recordType(), - rpOne.fullComponentTypes(), - newNested)); - } - } - } - } - } - - if (!current.equals(new HashSet<>(e.getValue()))) { - Set result = new HashSet<>(patterns); - result.removeAll(e.getValue()); - result.addAll(current); - return result; - } - } - return patterns; - } - - /* In the set of patterns, find those for which, given: - * $record($nested1, $nested2, ...) - * all the $nestedX pattern cover the given record component, - * and replace those with a simple binding pattern over $record. - */ - private Set reduceRecordPatterns(Set patterns) { - var newPatterns = new HashSet(); - boolean modified = false; - for (PatternDescription pd : patterns) { - if (pd instanceof RecordPattern rpOne) { - PatternDescription reducedPattern = reduceRecordPattern(rpOne); - if (reducedPattern != rpOne) { - newPatterns.add(reducedPattern); - modified = true; - continue; - } - } - newPatterns.add(pd); - } - return modified ? newPatterns : patterns; - } - - private PatternDescription reduceRecordPattern(PatternDescription pattern) { - if (pattern instanceof RecordPattern rpOne) { - Type[] componentType = rpOne.fullComponentTypes(); - //error recovery, ignore patterns with incorrect number of nested patterns: - if (componentType.length != rpOne.nested.length) { - return pattern; - } - PatternDescription[] reducedNestedPatterns = null; - boolean covered = true; - for (int i = 0; i < componentType.length; i++) { - PatternDescription newNested = reduceRecordPattern(rpOne.nested[i]); - if (newNested != rpOne.nested[i]) { - if (reducedNestedPatterns == null) { - reducedNestedPatterns = Arrays.copyOf(rpOne.nested, rpOne.nested.length); - } - reducedNestedPatterns[i] = newNested; - } - - covered &= checkCovered(componentType[i], List.of(newNested)); - } - if (covered) { - return new BindingPattern(rpOne.recordType); - } else if (reducedNestedPatterns != null) { - return new RecordPattern(rpOne.recordType, rpOne.fullComponentTypes(), reducedNestedPatterns); - } - } - return pattern; - } - - private Set removeCoveredRecordPatterns(Set patterns) { - Set existingBindings = patterns.stream() - .filter(pd -> pd instanceof BindingPattern) - .map(pd -> ((BindingPattern) pd).type.tsym) - .collect(Collectors.toSet()); - Set result = new HashSet<>(patterns); - - for (Iterator it = result.iterator(); it.hasNext();) { - PatternDescription pd = it.next(); - if (pd instanceof RecordPattern rp && existingBindings.contains(rp.recordType.tsym)) { - it.remove(); - } - } - - return result; - } - - private boolean isBpCovered(Type componentType, PatternDescription newNested) { - if (newNested instanceof BindingPattern bp) { - Type seltype = types.erasure(componentType); - Type pattype = types.erasure(bp.type); - - return seltype.isPrimitive() ? - types.isUnconditionallyExact(seltype, pattype) : - (bp.type.isPrimitive() && types.isUnconditionallyExact(types.unboxedType(seltype), bp.type)) || types.isSubtype(seltype, pattype); - } - return false; - } - - sealed interface PatternDescription { } - public PatternDescription makePatternDescription(Type selectorType, JCPattern pattern) { - if (pattern instanceof JCBindingPattern binding) { - Type type = !selectorType.isPrimitive() && types.isSubtype(selectorType, binding.type) - ? selectorType : binding.type; - return new BindingPattern(type); - } else if (pattern instanceof JCRecordPattern record) { - Type[] componentTypes; - - if (!record.type.isErroneous()) { - componentTypes = ((ClassSymbol) record.type.tsym).getRecordComponents() - .map(r -> types.memberType(record.type, r)) - .toArray(s -> new Type[s]); - } - else { - componentTypes = record.nested.map(t -> types.createErrorType(t.type)).toArray(s -> new Type[s]);; - } - - PatternDescription[] nestedDescriptions = - new PatternDescription[record.nested.size()]; - int i = 0; - for (List it = record.nested; - it.nonEmpty(); - it = it.tail, i++) { - Type componentType = i < componentTypes.length ? componentTypes[i] - : syms.errType; - nestedDescriptions[i] = makePatternDescription(types.erasure(componentType), it.head); - } - return new RecordPattern(record.type, componentTypes, nestedDescriptions); - } else if (pattern instanceof JCAnyPattern) { - return new BindingPattern(selectorType); - } else { - throw Assert.error(); - } - } - record BindingPattern(Type type) implements PatternDescription { - @Override - public int hashCode() { - return type.tsym.hashCode(); - } - @Override - public boolean equals(Object o) { - return o instanceof BindingPattern other && - type.tsym == other.type.tsym; - } - @Override - public String toString() { - return type.tsym + " _"; - } - } - record RecordPattern(Type recordType, int _hashCode, Type[] fullComponentTypes, PatternDescription... nested) implements PatternDescription { - - public RecordPattern(Type recordType, Type[] fullComponentTypes, PatternDescription[] nested) { - this(recordType, hashCode(-1, recordType, nested), fullComponentTypes, nested); - } - - @Override - public int hashCode() { - return _hashCode; - } - - @Override - public boolean equals(Object o) { - return o instanceof RecordPattern other && - recordType.tsym == other.recordType.tsym && - Arrays.equals(nested, other.nested); - } - - public int hashCode(int excludeComponent) { - return hashCode(excludeComponent, recordType, nested); - } - - public static int hashCode(int excludeComponent, Type recordType, PatternDescription... nested) { - int hash = 5; - hash = 41 * hash + recordType.tsym.hashCode(); - for (int i = 0; i < nested.length; i++) { - if (i != excludeComponent) { - hash = 41 * hash + nested[i].hashCode(); - } - } - return hash; - } - @Override - public String toString() { - return recordType.tsym + "(" + Arrays.stream(nested) - .map(pd -> pd.toString()) - .collect(Collectors.joining(", ")) + ")"; - } - } -} diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java index e74aed6a35703..3bbd007c66a65 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java @@ -27,7 +27,11 @@ package com.sun.tools.javac.comp; +import java.util.Map; +import java.util.Map.Entry; import java.util.HashMap; +import java.util.HashSet; +import java.util.Set; import java.util.function.Consumer; import com.sun.source.tree.LambdaExpressionTree.BodyKind; @@ -47,12 +51,20 @@ import static com.sun.tools.javac.code.Flags.*; import static com.sun.tools.javac.code.Flags.BLOCK; +import com.sun.tools.javac.code.Kinds.Kind; import static com.sun.tools.javac.code.Kinds.Kind.*; +import com.sun.tools.javac.code.Type.TypeVar; import static com.sun.tools.javac.code.TypeTag.BOOLEAN; import static com.sun.tools.javac.code.TypeTag.VOID; import com.sun.tools.javac.resources.CompilerProperties.Fragments; import static com.sun.tools.javac.tree.JCTree.Tag.*; import com.sun.tools.javac.util.JCDiagnostic.Fragment; +import java.util.Arrays; +import java.util.Iterator; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import static java.util.stream.Collectors.groupingBy; /** This pass implements dataflow analysis for Java programs though * different AST visitor steps. Liveness analysis (see AliveAnalyzer) checks that @@ -201,8 +213,8 @@ public class Flow { private TreeMaker make; private final Resolve rs; private final JCDiagnostic.Factory diags; - private final ExhaustivenessComputer exhaustiveness; private Env attrEnv; + private final Infer infer; public static Flow instance(Context context) { Flow instance = context.get(flowKey); @@ -324,9 +336,10 @@ protected Flow(Context context) { syms = Symtab.instance(context); types = Types.instance(context); chk = Check.instance(context); + infer = Infer.instance(context); rs = Resolve.instance(context); diags = JCDiagnostic.Factory.instance(context); - exhaustiveness = ExhaustivenessComputer.instance(context); + Source source = Source.instance(context); } /** @@ -696,7 +709,7 @@ public void visitSwitch(JCSwitch tree) { tree.isExhaustive = tree.hasUnconditionalPattern || TreeInfo.isErrorEnumSwitch(tree.selector, tree.cases); if (exhaustiveSwitch) { - tree.isExhaustive |= exhaustiveness.exhausts(tree.selector, tree.cases); + tree.isExhaustive |= exhausts(tree.selector, tree.cases); if (!tree.isExhaustive) { log.error(tree, Errors.NotExhaustiveStatement); } @@ -735,7 +748,7 @@ public void visitSwitchExpression(JCSwitchExpression tree) { TreeInfo.isErrorEnumSwitch(tree.selector, tree.cases)) { tree.isExhaustive = true; } else { - tree.isExhaustive = exhaustiveness.exhausts(tree.selector, tree.cases); + tree.isExhaustive = exhausts(tree.selector, tree.cases); } if (!tree.isExhaustive) { @@ -745,6 +758,429 @@ public void visitSwitchExpression(JCSwitchExpression tree) { alive = alive.or(resolveYields(tree, prevPendingExits)); } + private boolean exhausts(JCExpression selector, List cases) { + Set patternSet = new HashSet<>(); + Map> enum2Constants = new HashMap<>(); + Set booleanLiterals = new HashSet<>(Set.of(0, 1)); + for (JCCase c : cases) { + if (!TreeInfo.unguardedCase(c)) + continue; + + for (var l : c.labels) { + if (l instanceof JCPatternCaseLabel patternLabel) { + for (Type component : components(selector.type)) { + patternSet.add(makePatternDescription(component, patternLabel.pat)); + } + } else if (l instanceof JCConstantCaseLabel constantLabel) { + if (types.unboxedTypeOrType(selector.type).hasTag(TypeTag.BOOLEAN)) { + Object value = ((JCLiteral) constantLabel.expr).value; + booleanLiterals.remove(value); + } else { + Symbol s = TreeInfo.symbol(constantLabel.expr); + if (s != null && s.isEnum()) { + enum2Constants.computeIfAbsent(s.owner, x -> { + Set result = new HashSet<>(); + s.owner.members() + .getSymbols(sym -> sym.kind == Kind.VAR && sym.isEnum()) + .forEach(result::add); + return result; + }).remove(s); + } + } + } + } + } + + if (types.unboxedTypeOrType(selector.type).hasTag(TypeTag.BOOLEAN) && booleanLiterals.isEmpty()) { + return true; + } + + for (Entry> e : enum2Constants.entrySet()) { + if (e.getValue().isEmpty()) { + patternSet.add(new BindingPattern(e.getKey().type)); + } + } + Set patterns = patternSet; + boolean useHashes = true; + try { + boolean repeat = true; + while (repeat) { + Set updatedPatterns; + updatedPatterns = reduceBindingPatterns(selector.type, patterns); + updatedPatterns = reduceNestedPatterns(updatedPatterns, useHashes); + updatedPatterns = reduceRecordPatterns(updatedPatterns); + updatedPatterns = removeCoveredRecordPatterns(updatedPatterns); + repeat = !updatedPatterns.equals(patterns); + if (checkCovered(selector.type, patterns)) { + return true; + } + if (!repeat) { + //there may be situation like: + //class B permits S1, S2 + //patterns: R(S1, B), R(S2, S2) + //this might be joined to R(B, S2), as B could be rewritten to S2 + //but hashing in reduceNestedPatterns will not allow that + //disable the use of hashing, and use subtyping in + //reduceNestedPatterns to handle situations like this: + repeat = useHashes; + useHashes = false; + } else { + //if a reduction happened, make sure hashing in reduceNestedPatterns + //is enabled, as the hashing speeds up the process significantly: + useHashes = true; + } + patterns = updatedPatterns; + } + return checkCovered(selector.type, patterns); + } catch (CompletionFailure cf) { + chk.completionError(selector.pos(), cf); + return true; //error recovery + } + } + + private boolean checkCovered(Type seltype, Iterable patterns) { + for (Type seltypeComponent : components(seltype)) { + for (PatternDescription pd : patterns) { + if(isBpCovered(seltypeComponent, pd)) { + return true; + } + } + } + return false; + } + + private List components(Type seltype) { + return switch (seltype.getTag()) { + case CLASS -> { + if (seltype.isCompound()) { + if (seltype.isIntersection()) { + yield ((Type.IntersectionClassType) seltype).getComponents() + .stream() + .flatMap(t -> components(t).stream()) + .collect(List.collector()); + } + yield List.nil(); + } + yield List.of(types.erasure(seltype)); + } + case TYPEVAR -> components(((TypeVar) seltype).getUpperBound()); + default -> List.of(types.erasure(seltype)); + }; + } + + /* In a set of patterns, search for a sub-set of binding patterns that + * in combination exhaust their sealed supertype. If such a sub-set + * is found, it is removed, and replaced with a binding pattern + * for the sealed supertype. + */ + private Set reduceBindingPatterns(Type selectorType, Set patterns) { + Set existingBindings = patterns.stream() + .filter(pd -> pd instanceof BindingPattern) + .map(pd -> ((BindingPattern) pd).type.tsym) + .collect(Collectors.toSet()); + + for (PatternDescription pdOne : patterns) { + if (pdOne instanceof BindingPattern bpOne) { + Set toAdd = new HashSet<>(); + + for (Type sup : types.directSupertypes(bpOne.type)) { + ClassSymbol clazz = (ClassSymbol) types.erasure(sup).tsym; + + clazz.complete(); + + if (clazz.isSealed() && clazz.isAbstract() && + //if a binding pattern for clazz already exists, no need to analyze it again: + !existingBindings.contains(clazz)) { + ListBuffer bindings = new ListBuffer<>(); + //do not reduce to types unrelated to the selector type: + Type clazzErasure = types.erasure(clazz.type); + if (components(selectorType).stream() + .map(types::erasure) + .noneMatch(c -> types.isSubtype(clazzErasure, c))) { + continue; + } + + Set permitted = allPermittedSubTypes(clazz, csym -> { + Type instantiated; + if (csym.type.allparams().isEmpty()) { + instantiated = csym.type; + } else { + instantiated = infer.instantiatePatternType(selectorType, csym); + } + + return instantiated != null && types.isCastable(selectorType, instantiated); + }); + + for (PatternDescription pdOther : patterns) { + if (pdOther instanceof BindingPattern bpOther) { + Set currentPermittedSubTypes = + allPermittedSubTypes(bpOther.type.tsym, s -> true); + + PERMITTED: for (Iterator it = permitted.iterator(); it.hasNext();) { + Symbol perm = it.next(); + + for (Symbol currentPermitted : currentPermittedSubTypes) { + if (types.isSubtype(types.erasure(currentPermitted.type), + types.erasure(perm.type))) { + it.remove(); + continue PERMITTED; + } + } + if (types.isSubtype(types.erasure(perm.type), + types.erasure(bpOther.type))) { + it.remove(); + } + } + } + } + + if (permitted.isEmpty()) { + toAdd.add(new BindingPattern(clazz.type)); + } + } + } + + if (!toAdd.isEmpty()) { + Set newPatterns = new HashSet<>(patterns); + newPatterns.addAll(toAdd); + return newPatterns; + } + } + } + return patterns; + } + + private Set allPermittedSubTypes(TypeSymbol root, Predicate accept) { + Set permitted = new HashSet<>(); + List permittedSubtypesClosure = baseClasses(root); + + while (permittedSubtypesClosure.nonEmpty()) { + ClassSymbol current = permittedSubtypesClosure.head; + + permittedSubtypesClosure = permittedSubtypesClosure.tail; + + current.complete(); + + if (current.isSealed() && current.isAbstract()) { + for (Type t : current.getPermittedSubclasses()) { + ClassSymbol csym = (ClassSymbol) t.tsym; + + if (accept.test(csym)) { + permittedSubtypesClosure = permittedSubtypesClosure.prepend(csym); + permitted.add(csym); + } + } + } + } + + return permitted; + } + + private List baseClasses(TypeSymbol root) { + if (root instanceof ClassSymbol clazz) { + return List.of(clazz); + } else if (root instanceof TypeVariableSymbol tvar) { + ListBuffer result = new ListBuffer<>(); + for (Type bound : tvar.getBounds()) { + result.appendList(baseClasses(bound.tsym)); + } + return result.toList(); + } else { + return List.nil(); + } + } + + /* Among the set of patterns, find sub-set of patterns such: + * $record($prefix$, $nested, $suffix$) + * Where $record, $prefix$ and $suffix$ is the same for each pattern + * in the set, and the patterns only differ in one "column" in + * the $nested pattern. + * Then, the set of $nested patterns is taken, and passed recursively + * to reduceNestedPatterns and to reduceBindingPatterns, to + * simplify the pattern. If that succeeds, the original found sub-set + * of patterns is replaced with a new set of patterns of the form: + * $record($prefix$, $resultOfReduction, $suffix$) + * + * useHashes: when true, patterns will be subject to exact equivalence; + * when false, two binding patterns will be considered equivalent + * if one of them is more generic than the other one; + * when false, the processing will be significantly slower, + * as pattern hashes cannot be used to speed up the matching process + */ + private Set reduceNestedPatterns(Set patterns, + boolean useHashes) { + /* implementation note: + * finding a sub-set of patterns that only differ in a single + * column is time-consuming task, so this method speeds it up by: + * - group the patterns by their record class + * - for each column (nested pattern) do: + * -- group patterns by their hash + * -- in each such by-hash group, find sub-sets that only differ in + * the chosen column, and then call reduceBindingPatterns and reduceNestedPatterns + * on patterns in the chosen column, as described above + */ + var groupByRecordClass = + patterns.stream() + .filter(pd -> pd instanceof RecordPattern) + .map(pd -> (RecordPattern) pd) + .collect(groupingBy(pd -> (ClassSymbol) pd.recordType.tsym)); + + for (var e : groupByRecordClass.entrySet()) { + int nestedPatternsCount = e.getKey().getRecordComponents().size(); + Set current = new HashSet<>(e.getValue()); + + for (int mismatchingCandidate = 0; + mismatchingCandidate < nestedPatternsCount; + mismatchingCandidate++) { + int mismatchingCandidateFin = mismatchingCandidate; + var groupEquivalenceCandidates = + current + .stream() + //error recovery, ignore patterns with incorrect number of nested patterns: + .filter(pd -> pd.nested.length == nestedPatternsCount) + .collect(groupingBy(pd -> useHashes ? pd.hashCode(mismatchingCandidateFin) : 0)); + for (var candidates : groupEquivalenceCandidates.values()) { + var candidatesArr = candidates.toArray(RecordPattern[]::new); + + for (int firstCandidate = 0; + firstCandidate < candidatesArr.length; + firstCandidate++) { + RecordPattern rpOne = candidatesArr[firstCandidate]; + ListBuffer join = new ListBuffer<>(); + + join.append(rpOne); + + NEXT_PATTERN: for (int nextCandidate = 0; + nextCandidate < candidatesArr.length; + nextCandidate++) { + if (firstCandidate == nextCandidate) { + continue; + } + + RecordPattern rpOther = candidatesArr[nextCandidate]; + if (rpOne.recordType.tsym == rpOther.recordType.tsym) { + for (int i = 0; i < rpOne.nested.length; i++) { + if (i != mismatchingCandidate) { + if (!rpOne.nested[i].equals(rpOther.nested[i])) { + if (useHashes || + //when not using hashes, + //check if rpOne.nested[i] is + //a subtype of rpOther.nested[i]: + !(rpOne.nested[i] instanceof BindingPattern bpOne) || + !(rpOther.nested[i] instanceof BindingPattern bpOther) || + !types.isSubtype(types.erasure(bpOne.type), types.erasure(bpOther.type))) { + continue NEXT_PATTERN; + } + } + } + } + join.append(rpOther); + } + } + + var nestedPatterns = join.stream().map(rp -> rp.nested[mismatchingCandidateFin]).collect(Collectors.toSet()); + var updatedPatterns = reduceNestedPatterns(nestedPatterns, useHashes); + + updatedPatterns = reduceRecordPatterns(updatedPatterns); + updatedPatterns = removeCoveredRecordPatterns(updatedPatterns); + updatedPatterns = reduceBindingPatterns(rpOne.fullComponentTypes()[mismatchingCandidateFin], updatedPatterns); + + if (!nestedPatterns.equals(updatedPatterns)) { + if (useHashes) { + current.removeAll(join); + } + + for (PatternDescription nested : updatedPatterns) { + PatternDescription[] newNested = + Arrays.copyOf(rpOne.nested, rpOne.nested.length); + newNested[mismatchingCandidateFin] = nested; + current.add(new RecordPattern(rpOne.recordType(), + rpOne.fullComponentTypes(), + newNested)); + } + } + } + } + } + + if (!current.equals(new HashSet<>(e.getValue()))) { + Set result = new HashSet<>(patterns); + result.removeAll(e.getValue()); + result.addAll(current); + return result; + } + } + return patterns; + } + + /* In the set of patterns, find those for which, given: + * $record($nested1, $nested2, ...) + * all the $nestedX pattern cover the given record component, + * and replace those with a simple binding pattern over $record. + */ + private Set reduceRecordPatterns(Set patterns) { + var newPatterns = new HashSet(); + boolean modified = false; + for (PatternDescription pd : patterns) { + if (pd instanceof RecordPattern rpOne) { + PatternDescription reducedPattern = reduceRecordPattern(rpOne); + if (reducedPattern != rpOne) { + newPatterns.add(reducedPattern); + modified = true; + continue; + } + } + newPatterns.add(pd); + } + return modified ? newPatterns : patterns; + } + + private PatternDescription reduceRecordPattern(PatternDescription pattern) { + if (pattern instanceof RecordPattern rpOne) { + Type[] componentType = rpOne.fullComponentTypes(); + //error recovery, ignore patterns with incorrect number of nested patterns: + if (componentType.length != rpOne.nested.length) { + return pattern; + } + PatternDescription[] reducedNestedPatterns = null; + boolean covered = true; + for (int i = 0; i < componentType.length; i++) { + PatternDescription newNested = reduceRecordPattern(rpOne.nested[i]); + if (newNested != rpOne.nested[i]) { + if (reducedNestedPatterns == null) { + reducedNestedPatterns = Arrays.copyOf(rpOne.nested, rpOne.nested.length); + } + reducedNestedPatterns[i] = newNested; + } + + covered &= checkCovered(componentType[i], List.of(newNested)); + } + if (covered) { + return new BindingPattern(rpOne.recordType); + } else if (reducedNestedPatterns != null) { + return new RecordPattern(rpOne.recordType, rpOne.fullComponentTypes(), reducedNestedPatterns); + } + } + return pattern; + } + + private Set removeCoveredRecordPatterns(Set patterns) { + Set existingBindings = patterns.stream() + .filter(pd -> pd instanceof BindingPattern) + .map(pd -> ((BindingPattern) pd).type.tsym) + .collect(Collectors.toSet()); + Set result = new HashSet<>(patterns); + + for (Iterator it = result.iterator(); it.hasNext();) { + PatternDescription pd = it.next(); + if (pd instanceof RecordPattern rp && existingBindings.contains(rp.recordType.tsym)) { + it.remove(); + } + } + + return result; + } + public void visitTry(JCTry tree) { ListBuffer prevPendingExits = pendingExits; pendingExits = new ListBuffer<>(); @@ -890,6 +1326,18 @@ public void analyzeTree(Env env, JCTree tree, TreeMaker make) { } } + private boolean isBpCovered(Type componentType, PatternDescription newNested) { + if (newNested instanceof BindingPattern bp) { + Type seltype = types.erasure(componentType); + Type pattype = types.erasure(bp.type); + + return seltype.isPrimitive() ? + types.isUnconditionallyExact(seltype, pattype) : + (bp.type.isPrimitive() && types.isUnconditionallyExact(types.unboxedType(seltype), bp.type)) || types.isSubtype(seltype, pattype); + } + return false; + } + /** * This pass implements the second step of the dataflow analysis, namely * the exception analysis. This is to ensure that every checked exception that is @@ -3025,4 +3473,93 @@ public static Liveness from(boolean value) { } } + sealed interface PatternDescription { } + public PatternDescription makePatternDescription(Type selectorType, JCPattern pattern) { + if (pattern instanceof JCBindingPattern binding) { + Type type = !selectorType.isPrimitive() && types.isSubtype(selectorType, binding.type) + ? selectorType : binding.type; + return new BindingPattern(type); + } else if (pattern instanceof JCRecordPattern record) { + Type[] componentTypes; + + if (!record.type.isErroneous()) { + componentTypes = ((ClassSymbol) record.type.tsym).getRecordComponents() + .map(r -> types.memberType(record.type, r)) + .toArray(s -> new Type[s]); + } + else { + componentTypes = record.nested.map(t -> types.createErrorType(t.type)).toArray(s -> new Type[s]);; + } + + PatternDescription[] nestedDescriptions = + new PatternDescription[record.nested.size()]; + int i = 0; + for (List it = record.nested; + it.nonEmpty(); + it = it.tail, i++) { + Type componentType = i < componentTypes.length ? componentTypes[i] + : syms.errType; + nestedDescriptions[i] = makePatternDescription(types.erasure(componentType), it.head); + } + return new RecordPattern(record.type, componentTypes, nestedDescriptions); + } else if (pattern instanceof JCAnyPattern) { + return new BindingPattern(selectorType); + } else { + throw Assert.error(); + } + } + record BindingPattern(Type type) implements PatternDescription { + @Override + public int hashCode() { + return type.tsym.hashCode(); + } + @Override + public boolean equals(Object o) { + return o instanceof BindingPattern other && + type.tsym == other.type.tsym; + } + @Override + public String toString() { + return type.tsym + " _"; + } + } + record RecordPattern(Type recordType, int _hashCode, Type[] fullComponentTypes, PatternDescription... nested) implements PatternDescription { + + public RecordPattern(Type recordType, Type[] fullComponentTypes, PatternDescription[] nested) { + this(recordType, hashCode(-1, recordType, nested), fullComponentTypes, nested); + } + + @Override + public int hashCode() { + return _hashCode; + } + + @Override + public boolean equals(Object o) { + return o instanceof RecordPattern other && + recordType.tsym == other.recordType.tsym && + Arrays.equals(nested, other.nested); + } + + public int hashCode(int excludeComponent) { + return hashCode(excludeComponent, recordType, nested); + } + + public static int hashCode(int excludeComponent, Type recordType, PatternDescription... nested) { + int hash = 5; + hash = 41 * hash + recordType.tsym.hashCode(); + for (int i = 0; i < nested.length; i++) { + if (i != excludeComponent) { + hash = 41 * hash + nested[i].hashCode(); + } + } + return hash; + } + @Override + public String toString() { + return recordType.tsym + "(" + Arrays.stream(nested) + .map(pd -> pd.toString()) + .collect(Collectors.joining(", ")) + ")"; + } + } } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/CodeBlob.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/CodeBlob.java index 12469efc67e43..20c5fabf8bc95 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/CodeBlob.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/CodeBlob.java @@ -180,8 +180,6 @@ public ImmutableOopMapSet getOopMaps() { public boolean isUpcallStub() { return getKind() == UpcallKind; } - public boolean isContinuationStub() { return getName().equals("StubRoutines (continuation stubs)"); } - public boolean isJavaMethod() { return false; } public boolean isNativeMethod() { return false; } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ContinuationEntry.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ContinuationEntry.java deleted file mode 100644 index 73152bdee8421..0000000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ContinuationEntry.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2025, NTT DATA. - * 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 sun.jvm.hotspot.runtime; - -import sun.jvm.hotspot.debugger.*; -import sun.jvm.hotspot.runtime.*; -import sun.jvm.hotspot.types.*; - - -public class ContinuationEntry extends VMObject { - private static long size; - private static Address returnPC; - - static { - VM.registerVMInitializedObserver((o, d) -> initialize(VM.getVM().getTypeDataBase())); - } - - private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { - Type type = db.lookupType("ContinuationEntry"); - size = type.getSize(); - returnPC = type.getAddressField("_return_pc").getValue(); - } - - public ContinuationEntry(Address addr) { - super(addr); - } - - public Address getEntryPC() { - return returnPC; - } - - public Address getEntrySP(){ - return this.getAddress(); - } - - public Address getEntryFP(){ - return this.getAddress().addOffsetTo(size); - } - -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java index 826b5cecfd568..d92f464f0d2f6 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java @@ -47,7 +47,6 @@ public class JavaThread extends Thread { private static AddressField stackBaseField; private static CIntegerField stackSizeField; private static CIntegerField terminatedField; - private static AddressField contEntryField; private static AddressField activeHandlesField; private static CIntegerField monitorOwnerIDField; private static long oopPtrSize; @@ -96,7 +95,6 @@ private static synchronized void initialize(TypeDataBase db) { stackBaseField = type.getAddressField("_stack_base"); stackSizeField = type.getCIntegerField("_stack_size"); terminatedField = type.getCIntegerField("_terminated"); - contEntryField = type.getAddressField("_cont_entry"); activeHandlesField = type.getAddressField("_active_handles"); monitorOwnerIDField = type.getCIntegerField("_monitor_owner_id"); @@ -342,10 +340,6 @@ public int getTerminated() { return (int) terminatedField.getValue(addr); } - public ContinuationEntry getContEntry() { - return VMObjectFactory.newObject(ContinuationEntry.class, contEntryField.getValue(addr)); - } - /** Gets the Java-side thread object for this JavaThread */ public Oop getThreadObj() { Oop obj = null; diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/aarch64/AARCH64Frame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/aarch64/AARCH64Frame.java index 5ae4cb703b331..a5aa7ce440506 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/aarch64/AARCH64Frame.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/aarch64/AARCH64Frame.java @@ -270,13 +270,7 @@ public Frame sender(RegisterMap regMap, CodeBlob cb) { } if (cb != null) { - if (cb.isUpcallStub()) { - return senderForUpcallStub(map, (UpcallStub)cb); - } else if (cb.isContinuationStub()) { - return senderForContinuationStub(map, cb); - } else { - return senderForCompiledFrame(map, cb); - } + return cb.isUpcallStub() ? senderForUpcallStub(map, (UpcallStub)cb) : senderForCompiledFrame(map, cb); } // Must be native-compiled frame, i.e. the marshaling code for native @@ -362,16 +356,6 @@ private void updateMapWithSavedLink(RegisterMap map, Address savedFPAddr) { map.setLocation(fp, savedFPAddr); } - private Frame senderForContinuationStub(AARCH64RegisterMap map, CodeBlob cb) { - var contEntry = map.getThread().getContEntry(); - - Address senderSP = contEntry.getEntrySP(); - Address senderPC = contEntry.getEntryPC(); - Address senderFP = contEntry.getEntryFP(); - - return new AARCH64Frame(senderSP, senderFP, senderPC); - } - private Frame senderForCompiledFrame(AARCH64RegisterMap map, CodeBlob cb) { if (DEBUG) { System.out.println("senderForCompiledFrame"); diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ppc64/PPC64Frame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ppc64/PPC64Frame.java index cae034c96132a..f4ce5337e2fc7 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ppc64/PPC64Frame.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ppc64/PPC64Frame.java @@ -258,13 +258,7 @@ public Frame sender(RegisterMap regMap, CodeBlob cb) { } if (cb != null) { - if (cb.isUpcallStub()) { - return senderForUpcallStub(map, (UpcallStub)cb); - } else if (cb.isContinuationStub()) { - return senderForContinuationStub(map, cb); - } else { - return senderForCompiledFrame(map, cb); - } + return cb.isUpcallStub() ? senderForUpcallStub(map, (UpcallStub)cb) : senderForCompiledFrame(map, cb); } // Must be native-compiled frame, i.e. the marshaling code for native @@ -337,15 +331,6 @@ private Frame senderForInterpreterFrame(PPC64RegisterMap map) { return new PPC64Frame(sp, unextendedSP, getLink(), getSenderPC()); } - private Frame senderForContinuationStub(PPC64RegisterMap map, CodeBlob cb) { - var contEntry = map.getThread().getContEntry(); - - Address sp = contEntry.getEntrySP(); - Address pc = contEntry.getEntryPC(); - Address fp = contEntry.getEntryFP(); - - return new PPC64Frame(sp, fp, pc); - } private Frame senderForCompiledFrame(PPC64RegisterMap map, CodeBlob cb) { if (DEBUG) { diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64Frame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64Frame.java index 44c8f4c679ca8..e02e056f028cd 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64Frame.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64Frame.java @@ -262,13 +262,7 @@ public Frame sender(RegisterMap regMap, CodeBlob cb) { } if (cb != null) { - if (cb.isUpcallStub()) { - return senderForUpcallStub(map, (UpcallStub)cb); - } else if (cb.isContinuationStub()) { - return senderForContinuationStub(map, cb); - } else { - return senderForCompiledFrame(map, cb); - } + return cb.isUpcallStub() ? senderForUpcallStub(map, (UpcallStub)cb) : senderForCompiledFrame(map, cb); } // Must be native-compiled frame, i.e. the marshaling code for native @@ -354,16 +348,6 @@ private void updateMapWithSavedLink(RegisterMap map, Address savedFPAddr) { map.setLocation(fp, savedFPAddr); } - private Frame senderForContinuationStub(RISCV64RegisterMap map, CodeBlob cb) { - var contEntry = map.getThread().getContEntry(); - - Address senderSP = contEntry.getEntrySP(); - Address senderPC = contEntry.getEntryPC(); - Address senderFP = contEntry.getEntryFP(); - - return new RISCV64Frame(senderSP, senderFP, senderPC); - } - private Frame senderForCompiledFrame(RISCV64RegisterMap map, CodeBlob cb) { if (DEBUG) { System.out.println("senderForCompiledFrame"); diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java index 2d972d3df176c..3ee4f0a815892 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java @@ -270,13 +270,7 @@ public Frame sender(RegisterMap regMap, CodeBlob cb) { } if (cb != null) { - if (cb.isUpcallStub()) { - return senderForUpcallStub(map, (UpcallStub)cb); - } else if (cb.isContinuationStub()) { - return senderForContinuationStub(map, cb); - } else { - return senderForCompiledFrame(map, cb); - } + return cb.isUpcallStub() ? senderForUpcallStub(map, (UpcallStub)cb) : senderForCompiledFrame(map, cb); } // Must be native-compiled frame, i.e. the marshaling code for native @@ -362,16 +356,6 @@ private void updateMapWithSavedLink(RegisterMap map, Address savedFPAddr) { map.setLocation(rbp, savedFPAddr); } - private Frame senderForContinuationStub(X86RegisterMap map, CodeBlob cb) { - var contEntry = map.getThread().getContEntry(); - - Address senderSP = contEntry.getEntrySP(); - Address senderPC = contEntry.getEntryPC(); - Address senderFP = contEntry.getEntryFP(); - - return new X86Frame(senderSP, senderFP, senderPC); - } - private Frame senderForCompiledFrame(X86RegisterMap map, CodeBlob cb) { if (DEBUG) { System.out.println("senderForCompiledFrame"); diff --git a/src/jdk.httpserver/share/classes/module-info.java b/src/jdk.httpserver/share/classes/module-info.java index ac147582b1421..15e9e2cc36d1e 100644 --- a/src/jdk.httpserver/share/classes/module-info.java +++ b/src/jdk.httpserver/share/classes/module-info.java @@ -23,8 +23,6 @@ * questions. */ -import com.sun.net.httpserver.*; - /** * Defines the JDK-specific HTTP server API, and provides the jwebserver tool * for running a minimal HTTP server. @@ -111,14 +109,6 @@ * and implementation of the server does not intend to be a full-featured, high performance * HTTP server. * - * @implNote - * Prior to JDK 26, in the JDK default implementation, the {@link HttpExchange} attribute map was - * shared with the enclosing {@link HttpContext}. - * Since JDK 26, by default, exchange attributes are per-exchange and the context attributes must - * be accessed by calling {@link HttpExchange#getHttpContext() getHttpContext()}{@link - * HttpContext#getAttributes() .getAttributes()}.
    - * A new system property, {@systemProperty jdk.httpserver.attributes} (default value: {@code ""}) - * allows to revert this new behavior. Set this property to "context" to restore the pre JDK 26 behavior. * @toolGuide jwebserver * * @uses com.sun.net.httpserver.spi.HttpServerProvider diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/ExchangeImpl.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/ExchangeImpl.java index 0899952b4950f..3c1c5d1f3747d 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/ExchangeImpl.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/ExchangeImpl.java @@ -57,6 +57,8 @@ class ExchangeImpl { boolean close; boolean closed; boolean http10 = false; + boolean upgrade; + boolean upgraded; /* for formatting the Date: header */ private static final DateTimeFormatter FORMATTER; @@ -70,6 +72,7 @@ class ExchangeImpl { } private static final String HEAD = "HEAD"; + private static final String GET = "GET"; /* streams which take care of the HTTP protocol framing * and are passed up to higher layers @@ -95,6 +98,7 @@ class ExchangeImpl { this.uri = u; this.connection = connection; this.reqContentLen = len; + this.upgrade = isUpgradeRequest(reqHdrs); this.attributes = perExchangeAttributes ? new ConcurrentHashMap<>() : getHttpContext().getAttributes(); @@ -129,6 +133,15 @@ private boolean isHeadRequest() { return HEAD.equals(getRequestMethod()); } + // check if Upgrade connection + private boolean isUpgradeRequest(Headers headers) { + var values = headers.get("Connection"); + return values != null + && headers.get("Upgrade") != null + && GET.equals(getRequestMethod()) + && values.stream().filter("Upgrade"::equalsIgnoreCase).findAny().isPresent(); + } + public void close () { if (closed) { return; @@ -162,13 +175,14 @@ public InputStream getRequestBody () { if (uis != null) { return uis; } - if (reqContentLen == -1L) { + if (upgrade) { + uis_orig = new UpgradeInputStream(this, ris); + } else if (reqContentLen == -1L) { uis_orig = new ChunkedInputStream (this, ris); - uis = uis_orig; } else { uis_orig = new FixedLengthInputStream (this, ris, reqContentLen); - uis = uis_orig; } + uis = uis_orig; return uis; } @@ -221,11 +235,19 @@ public void sendResponseHeaders (int rCode, long contentLen) boolean noContentLengthHeader = false; // must not send Content-length is set rspHdrs.set("Date", FORMATTER.format(Instant.now())); - /* check for response type that is not allowed to send a body */ + /* check for connection upgrade */ + if (rCode == 101) { - if ((rCode>=100 && rCode <200) /* informational */ - ||(rCode == 204) /* no content */ - ||(rCode == 304)) /* not modified */ + if (contentLen != 0) { + logger.log( + Level.WARNING, + () -> "sendResponseHeaders: rCode = " + rCode + ": forcing contentLen = 0"); + } + contentLen = 0; + /* check for response type that is not allowed to send a body */ + } else if (rCode >= 100 && rCode < 200 /* informational */ + || rCode == 204 /* no content */ + || rCode == 304) /* not modified */ { if (contentLen != -1) { String msg = "sendResponseHeaders: rCode = "+ rCode @@ -253,6 +275,9 @@ public void sendResponseHeaders (int rCode, long contentLen) if (http10) { o.setWrappedStream (new UndefLengthOutputStream (this, ros)); close = true; + } else if (upgrade && rCode == 101) { + o.setWrappedStream (new UpgradeOutputStream (this, ros)); + close = true; } else { rspHdrs.set ("Transfer-encoding", "chunked"); o.setWrappedStream (new ChunkedOutputStream (this, ros)); @@ -291,6 +316,9 @@ public void sendResponseHeaders (int rCode, long contentLen) if (noContentToSend) { ros.flush(); close(); + } else if (upgrade && rCode == 101) { + upgraded = true; + ros.flush(); } server.logReply (rCode, req.requestLine(), null); } diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/IdentityWrapper.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/UpgradeInputStream.java similarity index 50% rename from src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/IdentityWrapper.java rename to src/jdk.httpserver/share/classes/sun/net/httpserver/UpgradeInputStream.java index 0a7a8cc8d4b24..b09d42588652b 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/IdentityWrapper.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/UpgradeInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2017, 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,52 +22,54 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package jdk.jpackage.internal.util; -import java.util.Objects; +package sun.net.httpserver; + +import java.io.IOException; +import java.io.InputStream; /** - * Object wrapper implementing {@link Object#equals(Object)} such that it - * returns {@code true} only when the argument is another instance of this class - * wrapping the same object. - *

    - * The class guarantees that {@link Object#equals(Object)} and - * {@link Object#hashCode()} methods of the wrapped object will never be called - * inside of the class methods. - * - * @param the type of the wrapped value + * A class which allows the caller to read the underlying stream for an upgrade request. + * close() does not close the underlying stream */ -public final class IdentityWrapper { +class UpgradeInputStream extends LeftOverInputStream { - public IdentityWrapper(T value) { - this.value = Objects.requireNonNull(value); + UpgradeInputStream(ExchangeImpl t, InputStream src) { + super(t, src); } - public T value() { - return value; + @Override + protected int readImpl(byte[] b, int off, int len) throws IOException { + if (!t.upgraded) { + return -1; + } + return in.read(b, off, len); } @Override - public int hashCode() { - return System.identityHashCode(value); + public int available() throws IOException { + if (!t.upgraded) { + return 0; + } + return in.available(); } @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if ((obj == null) || (getClass() != obj.getClass())) { - return false; - } - var other = (IdentityWrapper) obj; - return value == other.value; + public void reset() throws IOException { + throw new IOException("mark/reset not supported"); } @Override - public String toString() { - return String.format("Identity[%s]", value); + public void close() throws IOException { + closed = true; + t.getServerImpl().requestCompleted(t.getConnection()); } - private final T value; -} + @Override + public byte[] readAllBytes() throws IOException { + if (!t.upgraded) { + return new byte[0]; + } + throw new IOException("readAllBytes not supported for upgraded requests"); + } +} \ No newline at end of file diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/UpgradeOutputStream.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/UpgradeOutputStream.java new file mode 100644 index 0000000000000..c30d2ff662848 --- /dev/null +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/UpgradeOutputStream.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2007, 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 sun.net.httpserver; + +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.util.Objects; + +/** + * a class which allows the caller to write an indefinite number of bytes to an underlying stream. + * Used for upgraded connections only. + */ +class UpgradeOutputStream extends FilterOutputStream { + private boolean closed = false; + ExchangeImpl t; + + UpgradeOutputStream(ExchangeImpl t, OutputStream src) { + super(src); + this.t = t; + } + + @Override + public void write(int b) throws IOException { + if (closed) { + throw new IOException("stream closed"); + } + out.write(b); + } + + @Override + public void write(byte[] b, int off, int len) throws IOException { + Objects.checkFromIndexSize(off, len, b.length); + if (len == 0) { + return; + } + if (closed) { + throw new IOException("stream closed"); + } + out.write(b, off, len); + } + + @Override + public void close() throws IOException { + if (closed) { + return; + } + closed = true; + flush(); + LeftOverInputStream is = t.getOriginalInputStream(); + if (!is.isClosed()) { + is.close(); + } + Event e = new Event.WriteFinished(t); + t.getHttpContext().getServerImpl().addEvent(e); + out.close(); + } +} diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java index 66fcd90e2e84c..f364702ca12fd 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java @@ -331,7 +331,6 @@ protected void generateOtherFiles(ClassTree classTree) copyResource(DocPaths.LINK_SVG, DocPaths.RESOURCE_FILES.resolve(DocPaths.LINK_SVG), true); copyResource(DocPaths.MOON_SVG, DocPaths.RESOURCE_FILES.resolve(DocPaths.MOON_SVG), true); copyResource(DocPaths.SUN_SVG, DocPaths.RESOURCE_FILES.resolve(DocPaths.SUN_SVG), true); - copyResource(DocPaths.SORT_A_Z_SVG, DocPaths.RESOURCE_FILES.resolve(DocPaths.SORT_A_Z_SVG), true); if (options.createIndex()) { copyResource(DocPaths.SEARCH_JS_TEMPLATE, DocPaths.SCRIPT_FILES.resolve(DocPaths.SEARCH_JS), true); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlIds.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlIds.java index a3fba7eca1422..c257e1e153c86 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlIds.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlIds.java @@ -120,7 +120,6 @@ public class HtmlIds { static final HtmlId THEME_OS = HtmlId.of("theme-os"); static final HtmlId THEME_PANEL = HtmlId.of("theme-panel"); static final HtmlId UNNAMED_PACKAGE_ANCHOR = HtmlId.of("unnamed-package"); - static final HtmlId TOC_ORDER_TOGGLE = HtmlId.of("toc-lexical-order-toggle"); private static final String FIELDS_INHERITANCE = "fields-inherited-from-class-"; private static final String METHODS_INHERITANCE = "methods-inherited-from-class-"; private static final String NESTED_CLASSES_INHERITANCE = "nested-classes-inherited-from-class-"; diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TableOfContents.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TableOfContents.java index fab81914dbdc7..6a3dff8a5d61a 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TableOfContents.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TableOfContents.java @@ -112,16 +112,6 @@ protected Content toContent(boolean hasFilterInput) { .add(HtmlTree.INPUT(HtmlAttr.InputType.RESET, HtmlStyles.resetFilter) .put(HtmlAttr.TABINDEX, "-1") .put(HtmlAttr.VALUE, writer.resources.getText("doclet.filter_reset"))); - - header.add(Entity.NO_BREAK_SPACE) - .add(HtmlTree.BUTTON(HtmlStyles.tocSortToggle) - .setId(HtmlIds.TOC_ORDER_TOGGLE) - .add(HtmlTree.IMG(writer.pathToRoot.resolve(DocPaths.RESOURCE_FILES) - .resolve(DocPaths.SORT_A_Z_SVG), - writer.resources.getText("doclet.sort_table_of_contents") - )) - ); - } content.add(header); content.add(listBuilder); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyles.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyles.java index 7f33ebedfa4ae..358f490334b7e 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyles.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyles.java @@ -164,16 +164,6 @@ public enum HtmlStyles implements HtmlStyle { */ tocList, - /** - * The class used for lexical order toggle in the table of contents. - */ - tocSortToggle, - - /** - * The class used to indicate the state of the lexical sort toggle. - */ - tocSortIsActive, - // // diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script.js.template b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script.js.template index 235d0a87d2434..b91f99b2c428d 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script.js.template +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script.js.template @@ -23,14 +23,6 @@ const linkIcon = "##REPLACE:doclet.Link_icon##"; const linkToSection = "##REPLACE:doclet.Link_to_section##"; const toggleMemberListing = "##REPLACE:doclet.Toggle_member_listing##"; -const sortLexicalLabel = "##REPLACE:doclet.Sort_lexicographically##"; -const sortSourceLabel = "##REPLACE:doclet.Sort_by_source_order##"; -const TOC_ALPHA = "alpha"; -const TOC_SOURCE = "source"; -var origOlOrder = new Map(); -var origContainerOrder = new Map(); -var snapshotted = false; - if (typeof hljs !== "undefined") { try { hljs.highlightAll(); @@ -417,9 +409,6 @@ document.addEventListener("DOMContentLoaded", function(e) { makeFilterWidget(tocMenu, updateToc); var menuInput = tocMenu.querySelector("input.filter-input"); } - - snapshotAllOnce(); - document.addEventListener("keydown", (e) => { if (e.ctrlKey || e.altKey || e.metaKey) { return; @@ -651,168 +640,6 @@ document.addEventListener("DOMContentLoaded", function(e) { } window.addEventListener("scroll", handleScroll); } - - function allTocNavs() { - return Array.from(document.querySelectorAll("nav.toc")); - } - - function nestedTocLists(scope) { - const listsToSort = []; - const sectionLinks = scope.querySelectorAll("ol.toc-list > li > a"); - - sectionLinks.forEach(function(link) { - const href = link.getAttribute("href"); - if (href === "#constructor-detail" || href === "#method-detail" - || href === "#field-detail" || href === "#annotation-interface-element-detail" - || href === "#enum-constant-detail" || href === "#property-detail") { - const memberList = link.nextElementSibling; - if (memberList && memberList.tagName === 'OL') { - listsToSort.push(memberList); - } - } - }); - - return listsToSort; - } - - function textForLi(li) { - return li.querySelector(":scope > a").textContent.trim(); - } - - function alphaCompare(a, b) { - return textForLi(a).localeCompare(textForLi(b), undefined, { - numeric: true, - sensitivity: "base" - }); - } - - function snapshotTocOnce(nav){ - nestedTocLists(nav).forEach(function(ol){ - if (!origOlOrder.has(ol)) origOlOrder.set(ol, Array.from(ol.children)); - }); - } - function restoreToc(nav){ - nestedTocLists(nav).forEach(function(ol){ - var orig = origOlOrder.get(ol); - if (orig) orig.forEach(function(li){ ol.appendChild(li); }); - }); - } - function sortTocAlpha(nav){ - nestedTocLists(nav).forEach(function(ol){ - var lis = Array.from(ol.children); - if (lis.length < 2) return; - lis.slice().sort(alphaCompare).forEach(function(li){ ol.appendChild(li); }); - }); - } - - function snapshotAllOnce() { - if (snapshotted) return; - allTocNavs().forEach(snapshotTocOnce); - snapshotted = true; - } - - function restoreAllMemberContainers(){ - origContainerOrder.forEach(function(kids, container){ - kids.forEach(function(ch){ container.appendChild(ch); }); - }); - } - - function reorderMemberDetailsAlpha() { - var sidebarNav = document.querySelector(".main-grid nav.toc"); - var mainRoot = document.querySelector(".main-grid main"); - if (!sidebarNav || !mainRoot) return; - - var containers = Array.from( - mainRoot.querySelectorAll("ul.member-list") - ); - - containers.forEach(function(container) { - var links = Array.from(sidebarNav.querySelectorAll("a[href^='#']")).filter(function(a) { - var id = a.getAttribute("href").slice(1); - if (!id) return false; - var target = document.getElementById(decodeURI(id)); - return target && container.contains(target); - }); - if (links.length < 2) return; - - var items = links.map(function(a) { - var id = a.getAttribute("href").slice(1); - var target = document.getElementById(decodeURI(id)); - if (!target) return null; - var block = target.closest("section.detail, div.detail") || target; - var li = block.closest("li"); - if (li.parentElement !== container) return null; - return { - node: li, - text: (a.textContent || "").trim() - }; - }).filter(Boolean); - - if (items.length < 2) return; - - if (!origContainerOrder.has(container)) { - origContainerOrder.set(container, Array.from(container.children)); - } - - items.slice() - .sort(function(x, y) { - return x.text.localeCompare(y.text, undefined, { - numeric: true, - sensitivity: "base" - }); - }) - .forEach(function(it) { - container.appendChild(it.node); - }); - }); - } - - function updateToggleButtons(order){ - const next = (order === TOC_ALPHA) ? sortSourceLabel : sortLexicalLabel; - document.querySelectorAll(".toc-sort-toggle").forEach(function(btn){ - btn.setAttribute("aria-label", next); - btn.setAttribute("title", next); - btn.setAttribute("aria-pressed", order === TOC_ALPHA); - - if (order === TOC_ALPHA) { - btn.classList.add("toc-sort-is-active"); - } else { - btn.classList.remove("toc-sort-is-active"); - } - - var img = btn.querySelector("img"); - if (img) img.alt = next; - }); - } - - var tocOrder = TOC_SOURCE; - updateToggleButtons(tocOrder); - - function applyAlpha(){ - snapshotAllOnce(); - reorderMemberDetailsAlpha(); - allTocNavs().forEach(sortTocAlpha); - initSectionData(); handleScroll(); - updateToggleButtons(TOC_ALPHA); - tocOrder = TOC_ALPHA; - } - - function applySource(){ - snapshotAllOnce(); - restoreAllMemberContainers(); - allTocNavs().forEach(restoreToc); - initSectionData(); handleScroll(); - updateToggleButtons(TOC_SOURCE); - tocOrder = TOC_SOURCE; - } - - document.querySelectorAll(".toc-sort-toggle").forEach(function(btn) { - btn.addEventListener("click", function() { - if (tocOrder === TOC_SOURCE) applyAlpha(); else applySource(); - if (typeof btn.blur === "function") btn.blur(); - }); - }); - // Resize handler new ResizeObserver((entries) => { if (expanded) { diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/sort-a-z.svg b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/sort-a-z.svg deleted file mode 100644 index ea1ed38942edd..0000000000000 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/sort-a-z.svg +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css index 8da885a12cccd..4bb0fad4306ce 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css @@ -693,10 +693,10 @@ dl.name-value > dd { background-color: var(--toc-background-color); color: #666666; font-size: 0.76rem; + border: none; cursor: pointer; padding: 6px 10px; white-space: nowrap; - border: 1px solid transparent; } .main-grid nav.toc button > img { vertical-align: middle; @@ -1901,11 +1901,6 @@ table.striped > tbody > tr > th { .ui-autocomplete .search-result-desc { display: block; } - .top-nav nav.toc .toc-sort-toggle { - background: transparent; - border: 0; - margin-left: 4px; - } } @media screen and (max-width: 800px) { .about-language { @@ -1962,33 +1957,6 @@ pre.snippet .highlighted { background-color: var(--snippet-highlight-color); border-radius: 10%; } - -nav.toc div.toc-header input.filter-input { - flex: 1 1 auto; - min-width: 0; -} - -nav.toc div.toc-header .toc-sort-toggle { - flex: 0 0 auto; - position: static; - display: inline-flex; - align-items: center; - padding: .5em; - cursor: pointer; -} - -nav.toc div.toc-header .toc-sort-toggle > img { - width: 22px; - height: 22px; - vertical-align: middle; - filter: var(--icon-filter); -} - -nav.toc div.toc-header .toc-sort-toggle.toc-sort-is-active { - background-color: var(--toc-highlight-color); - border-radius: 4px; -} - /* * Hide navigation links and search box in print layout */ diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties index 6a15025044a2d..138a8fd004041 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets.properties @@ -251,14 +251,11 @@ doclet.Description=Description doclet.ConstantField=Constant Field doclet.Value=Value doclet.table_of_contents=Table of contents -doclet.Sort_lexicographically=Sort member details lexicographically -doclet.Sort_by_source_order=Sort member details by source order doclet.hide_sidebar=Hide sidebar doclet.show_sidebar=Show sidebar doclet.filter_label=Filter contents (type .) doclet.filter_table_of_contents=Filter table of contents doclet.filter_reset=Reset -doclet.sort_table_of_contents=Sort member details in lexicographical order doclet.linkMismatch_PackagedLinkedtoModule=The code being documented uses packages in the unnamed module, \ but the packages defined in {0} are in named modules. doclet.linkMismatch_ModuleLinkedtoPackage=The code being documented uses modules but the packages defined \ diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPaths.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPaths.java index f5672dcbf96eb..dbe91585aff8c 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPaths.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/DocPaths.java @@ -115,9 +115,6 @@ public static DocPath indexN(int n) { /** The name of the link icon file. */ public static final DocPath LINK_SVG = DocPath.create("link.svg"); - /** The name of the table of contents toggle icon file. */ - public static final DocPath SORT_A_Z_SVG = DocPath.create("sort-a-z.svg"); - /** The name of the right pointing angle icon. */ public static final DocPath RIGHT_SVG = DocPath.create("right.svg"); diff --git a/src/jdk.jcmd/share/man/jcmd.md b/src/jdk.jcmd/share/man/jcmd.md index af3886a915caa..4e67e7a450230 100644 --- a/src/jdk.jcmd/share/man/jcmd.md +++ b/src/jdk.jcmd/share/man/jcmd.md @@ -1,5 +1,5 @@ --- -# Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -704,7 +704,7 @@ The following commands are available: Impact: Low `Thread.dump_to_file` \[*options*\] *filepath* -: Dump all threads, with stack traces, to a file in plain text or JSON format. +: Dump threads, with stack traces, to a file in plain text or JSON format. Impact: Medium: Depends on the number of threads. @@ -723,8 +723,7 @@ The following commands are available: - *filepath*: The file path to the output file. If %p is specified in the filename, it is expanded to the JVM's PID. (FILE, no default value) `Thread.print` \[*options*\] -: Print all platform threads, and mounted virtual threads, with stack traces. - The Thread.dump_to_file command will print all threads to a file. +: Prints all threads with stacktraces. Impact: Medium --- depends on the number of threads. diff --git a/src/jdk.jconsole/share/classes/sun/tools/jconsole/ProxyClient.java b/src/jdk.jconsole/share/classes/sun/tools/jconsole/ProxyClient.java index 0ff2d0e366588..ec2290421a4bd 100644 --- a/src/jdk.jconsole/share/classes/sun/tools/jconsole/ProxyClient.java +++ b/src/jdk.jconsole/share/classes/sun/tools/jconsole/ProxyClient.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2022, 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 @@ -34,7 +34,6 @@ import static java.lang.management.ManagementFactory.*; import java.lang.ref.WeakReference; import java.lang.reflect.*; -import java.net.URI; import java.rmi.*; import java.rmi.registry.*; import java.rmi.server.*; @@ -134,24 +133,7 @@ private ProxyClient(String url, this.advancedUrl = url; this.connectionName = getConnectionName(url, userName); this.displayName = connectionName; - JMXServiceURL jmxServiceURL = new JMXServiceURL(url); - setParameters(jmxServiceURL, userName, password); - if ("rmi".equals(jmxServiceURL.getProtocol())) { - String path = jmxServiceURL.getURLPath(); - if (path.startsWith("/jndi/")) { - int end = path.indexOf(';'); - if (end < 0) end = path.length(); - String registryURIStr = path.substring(6, end); - URI registryURI = URI.create(registryURIStr); - if ("rmi".equals(registryURI.getScheme()) - && "/jmxrmi".equals(registryURI.getPath())) { - this.registryHostName = registryURI.getHost(); - this.registryPort = registryURI.getPort(); - this.vmConnector = true; - checkSslConfig(); - } - } - } + setParameters(new JMXServiceURL(url), userName, password); } private ProxyClient(LocalVirtualMachine lvm) throws IOException { diff --git a/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.c b/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.c index 2bed6b6bb281b..73ea9a295e681 100644 --- a/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.c +++ b/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -890,6 +890,8 @@ printUsage(void) " everything = 0xfff")); TTY_MESSAGE(( + "debugflags=flags debug flags (bitmask) none\n" + " USE_ITERATE_THROUGH_HEAP 0x01\n" "\n" "Environment Variables\n" "---------------------\n" @@ -1190,6 +1192,13 @@ parseOptions(char *options) } /*LINTED*/ logflags = (unsigned)strtol(current, NULL, 0); + } else if (strcmp(buf, "debugflags") == 0) { + /*LINTED*/ + if (!get_tok(&str, current, (int)(end - current), ',')) { + goto syntax_error; + } + /*LINTED*/ + gdata->debugflags = (unsigned)strtol(current, NULL, 0); } else if ( strcmp(buf, "suspend")==0 ) { if ( !get_boolean(&str, &suspendOnInit) ) { goto syntax_error; diff --git a/src/jdk.jdwp.agent/share/native/libjdwp/util.c b/src/jdk.jdwp.agent/share/native/libjdwp/util.c index 980c622cc48f0..45de2ba7b7aae 100644 --- a/src/jdk.jdwp.agent/share/native/libjdwp/util.c +++ b/src/jdk.jdwp.agent/share/native/libjdwp/util.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2730,6 +2730,10 @@ typedef struct ClassCountData { jvmtiError error; } ClassCountData; +/* Two different cbObjectCounter's, one for FollowReferences, one for + * IterateThroughHeap. Pick a card, any card. + */ + /* Callback for object count heap traversal (heap_reference_callback) */ static jint JNICALL cbObjectCounterFromRef(jvmtiHeapReferenceKind reference_kind, @@ -2791,6 +2795,38 @@ cbObjectCounterFromRef(jvmtiHeapReferenceKind reference_kind, return JVMTI_VISIT_OBJECTS; } +/* Callback for instance count heap traversal (heap_iteration_callback) */ +static jint JNICALL +cbObjectCounter(jlong class_tag, jlong size, jlong* tag_ptr, jint length, + void* user_data) +{ + ClassCountData *data; + int index; + + /* Check data structure */ + data = (ClassCountData*)user_data; + if (data == NULL) { + return JVMTI_VISIT_ABORT; + } + + /* Classes with no tag should be filtered out. */ + if ( class_tag == (jlong)0 ) { + data->error = AGENT_ERROR_INTERNAL; + return JVMTI_VISIT_ABORT; + } + + /* Class tag is actually an index into data arrays */ + index = CLASSTAG2INDEX(class_tag); + if (index < 0 || index >= data->classCount) { + data->error = AGENT_ERROR_ILLEGAL_ARGUMENT; + return JVMTI_VISIT_ABORT; + } + + /* Bump instance count on this class */ + data->counts[index]++; + return JVMTI_VISIT_OBJECTS; +} + /* Get instance counts for a set of classes */ jvmtiError classInstanceCounts(jint classCount, jclass *classes, jlong *counts) @@ -2843,27 +2879,53 @@ classInstanceCounts(jint classCount, jclass *classes, jlong *counts) /* Clear out callbacks structure */ (void)memset(&heap_callbacks,0,sizeof(heap_callbacks)); - /* Using FollowReferences only gives us live objects, but we - * need to tag the objects to avoid counting them twice since - * the callback is per reference. - * The jclass objects have been tagged with their index in the - * supplied list, and that tag may flip to negative if it - * is also an object of interest. - * All other objects being counted that weren't in the - * supplied classes list will have a negative classCount - * tag value. So all objects counted will have negative tags. - * If the absolute tag value is an index in the supplied - * list, then it's one of the supplied classes. - */ - data.negObjTag = -INDEX2CLASSTAG(classCount); + /* Check debug flags to see how to do this. */ + if ( (gdata->debugflags & USE_ITERATE_THROUGH_HEAP) == 0 ) { + + /* Using FollowReferences only gives us live objects, but we + * need to tag the objects to avoid counting them twice since + * the callback is per reference. + * The jclass objects have been tagged with their index in the + * supplied list, and that tag may flip to negative if it + * is also an object of interest. + * All other objects being counted that weren't in the + * supplied classes list will have a negative classCount + * tag value. So all objects counted will have negative tags. + * If the absolute tag value is an index in the supplied + * list, then it's one of the supplied classes. + */ + data.negObjTag = -INDEX2CLASSTAG(classCount); - /* Setup callbacks, only using object reference callback */ - heap_callbacks.heap_reference_callback = &cbObjectCounterFromRef; + /* Setup callbacks, only using object reference callback */ + heap_callbacks.heap_reference_callback = &cbObjectCounterFromRef; - /* Follow references, no initiating object, tagged classes only */ - error = JVMTI_FUNC_PTR(jvmti,FollowReferences) - (jvmti, JVMTI_HEAP_FILTER_CLASS_UNTAGGED, - NULL, NULL, &heap_callbacks, &data); + /* Follow references, no initiating object, tagged classes only */ + error = JVMTI_FUNC_PTR(jvmti,FollowReferences) + (jvmti, JVMTI_HEAP_FILTER_CLASS_UNTAGGED, + NULL, NULL, &heap_callbacks, &data); + + } else { + + /* Using IterateThroughHeap means that we will visit each object + * once, so no special tag tricks here. Just simple counting. + * However in this case the object might not be live, so we do + * a GC beforehand to make sure we minimize this. + */ + + /* FIXUP: Need some kind of trigger here to avoid excessive GC's? */ + error = JVMTI_FUNC_PTR(jvmti,ForceGarbageCollection)(jvmti); + if ( error != JVMTI_ERROR_NONE ) { + + /* Setup callbacks, just need object callback */ + heap_callbacks.heap_iteration_callback = &cbObjectCounter; + + /* Iterate through entire heap, tagged classes only */ + error = JVMTI_FUNC_PTR(jvmti,IterateThroughHeap) + (jvmti, JVMTI_HEAP_FILTER_CLASS_UNTAGGED, + NULL, &heap_callbacks, &data); + + } + } /* Use data error if needed */ if ( error == JVMTI_ERROR_NONE ) { diff --git a/src/jdk.jdwp.agent/share/native/libjdwp/util.h b/src/jdk.jdwp.agent/share/native/libjdwp/util.h index a48c8ba2c095e..3d499d7d56985 100644 --- a/src/jdk.jdwp.agent/share/native/libjdwp/util.h +++ b/src/jdk.jdwp.agent/share/native/libjdwp/util.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -92,6 +92,12 @@ typedef struct { jboolean quiet; jboolean jvmti_data_dump; /* If true, then support JVMTI DATA_DUMP_REQUEST events. */ + /* Debug flags (bit mask) */ + int debugflags; + + /* Possible debug flags */ + #define USE_ITERATE_THROUGH_HEAP 0X001 + char * options; jclass classClass; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventDirectoryStream.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventDirectoryStream.java index c8db9aef169e5..46dab564ac0fb 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventDirectoryStream.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventDirectoryStream.java @@ -257,11 +257,6 @@ private void processOrdered(Dispatcher c) throws IOException { } for (int i = 0; i < index; i++) { c.dispatch(sortedCache[i]); - sortedCache[i] = null; - } - // Shrink array - if (index > 100_000 && 4 * index < sortedCache.length) { - sortedCache = new RecordedEvent[2 * index]; } onFlush(); return; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventFileStream.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventFileStream.java index 82712fcbedc49..56d9fe01d790c 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventFileStream.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventFileStream.java @@ -127,10 +127,6 @@ private void processOrdered(Dispatcher c) throws IOException { cacheSorted[index++] = event; } dispatchOrdered(c, index); - if (index > 100_000 && 4 * index < cacheSorted.length) { - cacheSorted = new RecordedEvent[2 * index]; - } - onFlush(); index = 0; } } @@ -140,8 +136,8 @@ private void dispatchOrdered(Dispatcher c, int index) { Arrays.sort(cacheSorted, 0, index, EVENT_COMPARATOR); for (int i = 0; i < index; i++) { c.dispatch(cacheSorted[i]); - cacheSorted[i] = null; } + onFlush(); } private void processUnordered(Dispatcher c) throws IOException { diff --git a/src/jdk.jlink/share/man/jlink.md b/src/jdk.jlink/share/man/jlink.md index dc256af43b5f1..74f2d119c6980 100644 --- a/src/jdk.jlink/share/man/jlink.md +++ b/src/jdk.jlink/share/man/jlink.md @@ -1,5 +1,5 @@ --- -# Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -279,6 +279,8 @@ Suggested providers: java.smartcardio provides java.security.Provider used by java.base java.xml.crypto provides java.security.Provider used by java.base jdk.crypto.cryptoki provides java.security.Provider used by java.base + jdk.crypto.ec provides java.security.Provider used by java.base + jdk.crypto.mscapi provides java.security.Provider used by java.base jdk.security.jgss provides java.security.Provider used by java.base ``` diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/AppImageSigner.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/AppImageSigner.java index 1345597e3527b..571f163f682bb 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/AppImageSigner.java +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/AppImageSigner.java @@ -106,7 +106,7 @@ private void sign(MacApplication app, MacBundle appImage) throws CodesignExcepti throw new IllegalArgumentException(); } - app = copyWithUnresolvedAppImageLayout(app); + app = normalizeAppImageLayout(app); final var fileFilter = new SignFilter(app, appImage); @@ -243,7 +243,7 @@ static Codesigners create(CodesignConfig signingCfg) { } } - private static MacApplication copyWithUnresolvedAppImageLayout(MacApplication app) { + private static MacApplication normalizeAppImageLayout(MacApplication app) { switch (app.imageLayout()) { case MacApplicationLayout macLayout -> { return MacApplicationBuilder.overrideAppImageLayout(app, APPLICATION_LAYOUT); diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacBaseInstallerBundler.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacBaseInstallerBundler.java index 5c912728c32d5..f46b5a328fd85 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacBaseInstallerBundler.java +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacBaseInstallerBundler.java @@ -26,8 +26,14 @@ package jdk.jpackage.internal; import static jdk.jpackage.internal.StandardBundlerParam.PREDEFINED_APP_IMAGE; +import static jdk.jpackage.internal.StandardBundlerParam.PREDEFINED_APP_IMAGE_FILE; +import static jdk.jpackage.internal.StandardBundlerParam.SIGN_BUNDLE; +import java.nio.file.Files; +import java.nio.file.Path; +import java.text.MessageFormat; import java.util.Map; +import java.util.Optional; import jdk.jpackage.internal.model.ConfigException; public abstract class MacBaseInstallerBundler extends AbstractBundler { @@ -38,7 +44,26 @@ public MacBaseInstallerBundler() { protected void validateAppImageAndBundeler( Map params) throws ConfigException { - if (PREDEFINED_APP_IMAGE.fetchFrom(params) == null) { + if (PREDEFINED_APP_IMAGE.fetchFrom(params) != null) { + Path applicationImage = PREDEFINED_APP_IMAGE.fetchFrom(params); + if (new MacAppImageFileExtras(PREDEFINED_APP_IMAGE_FILE.fetchFrom(params)).signed()) { + var appLayout = ApplicationLayoutUtils.PLATFORM_APPLICATION_LAYOUT.resolveAt(applicationImage); + if (!Files.exists( + PackageFile.getPathInAppImage(appLayout))) { + Log.info(MessageFormat.format(I18N.getString( + "warning.per.user.app.image.signed"), + PackageFile.getPathInAppImage(appLayout))); + } + } else { + if (Optional.ofNullable( + SIGN_BUNDLE.fetchFrom(params)).orElse(Boolean.FALSE)) { + // if signing bundle with app-image, warn user if app-image + // is not already signed. + Log.info(MessageFormat.format(I18N.getString( + "warning.unsigned.app.image"), getID())); + } + } + } else { appImageBundler.validate(params); } } diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacFromParams.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacFromParams.java index e2d8750e39c93..7a881c846ff46 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacFromParams.java +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacFromParams.java @@ -99,7 +99,7 @@ private static MacApplication createMacApplication( // AppImageFile assumes the main launcher start up info is available when // it is constructed from Application instance. // This happens when jpackage signs predefined app image. - final var mainLauncherStartupInfo = new MainLauncherStartupInfo(superAppBuilder.mainLauncherClassName().orElseThrow()); + final var mainLauncherStartupInfo = new MainLauncherStartupInfo(PREDEFINED_APP_IMAGE_FILE.fetchFrom(params).getMainClass()); final var launchers = superAppBuilder.launchers().orElseThrow(); final var mainLauncher = ApplicationBuilder.overrideLauncherStartupInfo(launchers.mainLauncher(), mainLauncherStartupInfo); superAppBuilder.launchers(new ApplicationLaunchers(MacLauncher.create(mainLauncher), launchers.additionalLaunchers())); @@ -122,7 +122,7 @@ private static MacApplication createMacApplication( final boolean appStore; if (hasPredefinedAppImage(params) && PACKAGE_TYPE.findIn(params).filter(Predicate.isEqual("app-image")).isEmpty()) { - final var appImageFileExtras = new MacAppImageFileExtras(superAppBuilder.externalApplication().orElseThrow()); + final var appImageFileExtras = new MacAppImageFileExtras(PREDEFINED_APP_IMAGE_FILE.fetchFrom(params)); sign = appImageFileExtras.signed(); appStore = appImageFileExtras.appStore(); } else { diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPackageBuilder.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPackageBuilder.java index 9576f6a6a996e..cf5c6a934f733 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPackageBuilder.java +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPackageBuilder.java @@ -24,10 +24,8 @@ */ package jdk.jpackage.internal; -import static jdk.jpackage.internal.MacPackagingPipeline.APPLICATION_LAYOUT; import static jdk.jpackage.internal.MacPackagingPipeline.LayoutUtils.packagerLayout; -import java.nio.file.Files; import java.util.Objects; import jdk.jpackage.internal.model.ConfigException; import jdk.jpackage.internal.model.MacApplication; @@ -59,21 +57,7 @@ MacPackage create() throws ConfigException { .installedPackageLayout(pkg.installedPackageLayout()); pkg = pkgBuilder.create(); - - var macPkg = MacPackage.create(pkg, new MacPackageMixin.Stub(pkg.predefinedAppImage().map(v -> predefinedAppImageSigned))); - validatePredefinedAppImage(macPkg); - return macPkg; - } - - private static void validatePredefinedAppImage(MacPackage pkg) { - if (pkg.predefinedAppImageSigned().orElse(false)) { - pkg.predefinedAppImage().ifPresent(predefinedAppImage -> { - var thePackageFile = PackageFile.getPathInAppImage(APPLICATION_LAYOUT); - if (!Files.exists(predefinedAppImage.resolve(thePackageFile))) { - Log.info(I18N.format("warning.per.user.app.image.signed", thePackageFile)); - } - }); - } + return MacPackage.create(pkg, new MacPackageMixin.Stub(pkg.predefinedAppImage().map(v -> predefinedAppImageSigned))); } private final PackageBuilder pkgBuilder; diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPkgPackageBuilder.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPkgPackageBuilder.java index 663b8b16265a0..131650aebb516 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPkgPackageBuilder.java +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacPkgPackageBuilder.java @@ -43,9 +43,7 @@ MacPkgPackageBuilder signingBuilder(SigningIdentityBuilder v) { } MacPkgPackage create() throws ConfigException { - var pkg = MacPkgPackage.create(pkgBuilder.create(), new MacPkgPackageMixin.Stub(createSigningConfig())); - validatePredefinedAppImage(pkg); - return pkg; + return MacPkgPackage.create(pkgBuilder.create(), new MacPkgPackageMixin.Stub(createSigningConfig())); } private Optional createSigningConfig() throws ConfigException { @@ -58,14 +56,6 @@ private Optional createSigningConfig() throws ConfigException } } - private static void validatePredefinedAppImage(MacPkgPackage pkg) { - if (!pkg.predefinedAppImageSigned().orElse(false) && pkg.sign()) { - pkg.predefinedAppImage().ifPresent(predefinedAppImage -> { - Log.info(I18N.format("warning.unsigned.app.image", "pkg")); - }); - } - } - private final MacPackageBuilder pkgBuilder; private SigningIdentityBuilder signingBuilder; } diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ApplicationBuilder.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ApplicationBuilder.java index 9b5ed5b3b0817..141a1b5155f15 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ApplicationBuilder.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ApplicationBuilder.java @@ -86,9 +86,6 @@ ApplicationBuilder runtimeBuilder(RuntimeBuilder v) { ApplicationBuilder initFromExternalApplication(ExternalApplication app, Function mapper) { - - externalApp = Objects.requireNonNull(app); - if (version == null) { version = app.getAppVersion(); } @@ -115,19 +112,6 @@ Optional launchers() { return Optional.ofNullable(launchers); } - Optional externalApplication() { - return Optional.ofNullable(externalApp); - } - - Optional mainLauncherClassName() { - return launchers() - .map(ApplicationLaunchers::mainLauncher) - .flatMap(Launcher::startupInfo) - .map(LauncherStartupInfo::qualifiedClassName).or(() -> { - return externalApplication().map(ExternalApplication::getMainClass); - }); - } - ApplicationBuilder appImageLayout(AppImageLayout v) { appImageLayout = v; return this; @@ -224,7 +208,6 @@ String copyright() { private String vendor; private String copyright; private Path srcDir; - private ExternalApplication externalApp; private List contentDirs; private AppImageLayout appImageLayout; private RuntimeBuilder runtimeBuilder; diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ApplicationImageUtils.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ApplicationImageUtils.java index cda5b6c79ef28..7d3250ff7b9f7 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ApplicationImageUtils.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ApplicationImageUtils.java @@ -32,7 +32,6 @@ import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.Path; -import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -149,7 +148,6 @@ private static void copyRecursive(Path srcDir, Path dstDir, List excludeDi } } - FileUtils.copyRecursive(srcDir, dstDir.toAbsolutePath(), excludes, - LinkOption.NOFOLLOW_LINKS, StandardCopyOption.REPLACE_EXISTING); + FileUtils.copyRecursive(srcDir, dstDir.toAbsolutePath(), excludes, LinkOption.NOFOLLOW_LINKS); } } diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/Arguments.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/Arguments.java index f0323bbd84143..f9a5429a8bfa9 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/Arguments.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/Arguments.java @@ -125,7 +125,7 @@ public Arguments(String[] args) { for (String arg : args) { argList.add(arg); } - + Log.verbose ("\njpackage argument list: \n" + argList + "\n"); pos = 0; deployParams = new DeployParams(); diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/FromParams.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/FromParams.java index 8cfab61c9c099..56f2b46ea8f64 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/FromParams.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/FromParams.java @@ -120,7 +120,7 @@ static ApplicationBuilder createApplicationBuilder(Map p final var runtimeBuilderBuilder = new RuntimeBuilderBuilder(); - runtimeBuilderBuilder.modulePath(MODULE_PATH.fetchFrom(params)); + MODULE_PATH.copyInto(params, runtimeBuilderBuilder::modulePath); predefinedRuntimeDirectory.ifPresentOrElse(runtimeBuilderBuilder::forRuntime, () -> { final var startupInfos = launchers.asList().stream() diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/IOUtils.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/IOUtils.java index 427051719bb71..13c7a78b502ff 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/IOUtils.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/IOUtils.java @@ -25,6 +25,8 @@ package jdk.jpackage.internal; +import java.io.BufferedReader; +import java.io.InputStreamReader; import java.io.IOException; import java.io.PrintStream; import java.nio.file.Files; @@ -43,13 +45,33 @@ final class IOUtils { public static void copyFile(Path sourceFile, Path destFile) throws IOException { - Files.createDirectories(destFile.getParent()); + Files.createDirectories(getParent(destFile)); Files.copy(sourceFile, destFile, StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.COPY_ATTRIBUTES); } + public static boolean exists(Path path) { + if (path == null) { + return false; + } + + return Files.exists(path); + } + + // run "launcher paramfile" in the directory where paramfile is kept + public static void run(String launcher, Path paramFile) + throws IOException { + if (IOUtils.exists(paramFile)) { + ProcessBuilder pb = + new ProcessBuilder(launcher, + getFileName(paramFile).toString()); + pb = pb.directory(getParent(paramFile).toFile()); + exec(pb); + } + } + public static void exec(ProcessBuilder pb) throws IOException { exec(pb, false, null, false, Executor.INFINITE_TIMEOUT); @@ -61,6 +83,21 @@ public static void exec(ProcessBuilder pb, long timeout) exec(pb, false, null, false, timeout); } + // See JDK-8236282 + // Reading output from some processes (currently known "hdiutil attach") + // might hang even if process already exited. Only possible workaround found + // in "hdiutil attach" case is to redirect the output to a temp file and then + // read this file back. + public static void exec(ProcessBuilder pb, boolean writeOutputToFile) + throws IOException { + exec(pb, false, null, writeOutputToFile, Executor.INFINITE_TIMEOUT); + } + + static void exec(ProcessBuilder pb, boolean testForPresenceOnly, + PrintStream consumer) throws IOException { + exec(pb, testForPresenceOnly, consumer, false, Executor.INFINITE_TIMEOUT); + } + static void exec(ProcessBuilder pb, boolean testForPresenceOnly, PrintStream consumer, boolean writeOutputToFile, long timeout) throws IOException { @@ -90,6 +127,51 @@ static void exec(ProcessBuilder pb, boolean testForPresenceOnly, } } + public static int getProcessOutput(List result, String... args) + throws IOException, InterruptedException { + + ProcessBuilder pb = new ProcessBuilder(args); + + final Process p = pb.start(); + + List list = new ArrayList<>(); + + final BufferedReader in = + new BufferedReader(new InputStreamReader(p.getInputStream())); + final BufferedReader err = + new BufferedReader(new InputStreamReader(p.getErrorStream())); + + Thread t = new Thread(() -> { + try { + String line; + while ((line = in.readLine()) != null) { + list.add(line); + } + } catch (IOException ioe) { + Log.verbose(ioe); + } + + try { + String line; + while ((line = err.readLine()) != null) { + Log.error(line); + } + } catch (IOException ioe) { + Log.verbose(ioe); + } + }); + t.setDaemon(true); + t.start(); + + int ret = p.waitFor(); + Log.verbose(pb.command(), list, ret, IOUtils.getPID(p)); + + result.clear(); + result.addAll(list); + + return ret; + } + static void writableOutputDir(Path outdir) throws PackagerException { if (!Files.isDirectory(outdir)) { try { @@ -106,6 +188,28 @@ static void writableOutputDir(Path outdir) throws PackagerException { } } + public static Path getParent(Path p) { + Path parent = p.getParent(); + if (parent == null) { + IllegalArgumentException iae = + new IllegalArgumentException(p.toString()); + Log.verbose(iae); + throw iae; + } + return parent; + } + + public static Path getFileName(Path p) { + Path filename = p.getFileName(); + if (filename == null) { + IllegalArgumentException iae = + new IllegalArgumentException(p.toString()); + Log.verbose(iae); + throw iae; + } + return filename; + } + public static long getPID(Process p) { try { return p.pid(); diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/JLinkRuntimeBuilder.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/JLinkRuntimeBuilder.java index 2273d385936e1..bd82b34d897d4 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/JLinkRuntimeBuilder.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/JLinkRuntimeBuilder.java @@ -23,10 +23,8 @@ * questions. */ package jdk.jpackage.internal; -import static jdk.jpackage.internal.model.RuntimeBuilder.getDefaultModulePath; import java.io.File; -import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.lang.module.Configuration; @@ -34,7 +32,6 @@ import java.lang.module.ModuleFinder; import java.lang.module.ModuleReference; import java.lang.module.ResolvedModule; -import java.nio.file.Files; import java.nio.file.Path; import java.text.MessageFormat; import java.util.ArrayList; @@ -96,52 +93,6 @@ static RuntimeBuilder createJLinkRuntimeBuilder(List modulePath, Set - * Returns the specified path list if "java.base" module can be found in one of - * the paths from the specified path list. - *

    - * Returns a new path list created from the specified path list with the path of - * "java.base" module in the current runtime appended otherwise. - * - * @param modulePath the path list where to look up for "java.base" module - * @return the path list that includes location of "java.base" module - */ - static List ensureBaseModuleInModulePath(List modulePath) { - if (modulePath.stream().anyMatch(path -> { - return Files.isRegularFile(path.resolve("java.base.jmod")); - })) { - return modulePath; - } else { - // There is no "java.base.jmod" file in the `modulePath` path list. - // Pick items from the default module path list that are not yet - // in the `modulePath` path list and append them to it. - - var missingDefaultModulePath = getDefaultModulePath(); - - if (!modulePath.isEmpty()) { - missingDefaultModulePath.stream().filter(defaultPath -> { - return modulePath.stream().anyMatch(path -> { - try { - return Files.isSameFile(path, defaultPath); - } catch (IOException ex) { - // Assume `defaultPath` path doesn't exist in `modulePath` list. - return false; - } - }); - }).toList(); - } - - if (missingDefaultModulePath.isEmpty()) { - return modulePath; - } else { - return Stream.of(modulePath, missingDefaultModulePath).flatMap(Collection::stream).toList(); - } - } - } - private static List createJLinkCmdline(List modulePath, Set addModules, Set limitModules, List options, List startupInfos) throws ConfigException { List launcherModules = startupInfos.stream().map(si -> { @@ -264,7 +215,7 @@ private static String getPathList(List pathList) { } private static String getStringList(Set strings) { - return strings.stream().sorted().collect(Collectors.joining(",")); + return strings.stream().collect(Collectors.joining(",")); } private final List jlinkCmdLine; @@ -279,5 +230,5 @@ private static class LazyLoad { static final ToolProvider JLINK_TOOL = ToolProvider.findFirst( "jlink").orElseThrow(); - } + }; } diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/OverridableResource.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/OverridableResource.java index 73fc36d78acce..0099491fc7309 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/OverridableResource.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/OverridableResource.java @@ -31,7 +31,6 @@ import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; -import java.io.UncheckedIOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; @@ -181,15 +180,6 @@ OverridableResource setExternal(File v) { return setExternal(toPath(v)); } - Source probe() { - try { - return saveToStream(null); - } catch (IOException ex) { - // Should never happen. - throw new UncheckedIOException(ex); - } - } - Source saveToStream(OutputStream dest) throws IOException { if (dest == null) { return sendToConsumer(null); diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/StandardBundlerParam.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/StandardBundlerParam.java index 2b35a6830f870..6b89bb3ee65f5 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/StandardBundlerParam.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/StandardBundlerParam.java @@ -43,6 +43,7 @@ import jdk.jpackage.internal.model.ConfigException; import jdk.jpackage.internal.model.ExternalApplication; import static jdk.jpackage.internal.ApplicationLayoutUtils.PLATFORM_APPLICATION_LAYOUT; +import static jdk.jpackage.internal.model.RuntimeBuilder.getDefaultModulePath; /** * Standard bundler parameters. @@ -55,6 +56,7 @@ */ final class StandardBundlerParam { + private static final String JAVABASEJMOD = "java.base.jmod"; private static final String DEFAULT_VERSION = "1.0"; private static final String DEFAULT_RELEASE = "1"; private static final String[] DEFAULT_JLINK_OPTIONS = { @@ -413,14 +415,47 @@ final class StandardBundlerParam { new BundlerParamInfo<>( Arguments.CLIOptions.MODULE_PATH.getId(), (Class>) (Object)List.class, - p -> JLinkRuntimeBuilder.ensureBaseModuleInModulePath(List.of()), + p -> getDefaultModulePath(), (s, p) -> { List modulePath = Stream.of(s.split(File.pathSeparator)) .map(Path::of) .toList(); - return JLinkRuntimeBuilder.ensureBaseModuleInModulePath(modulePath); + Path javaBasePath = findPathOfModule(modulePath, JAVABASEJMOD); + + // Add the default JDK module path to the module path. + if (javaBasePath == null) { + List jdkModulePath = getDefaultModulePath(); + + if (jdkModulePath != null) { + modulePath = Stream.concat(modulePath.stream(), + jdkModulePath.stream()).toList(); + javaBasePath = findPathOfModule(modulePath, JAVABASEJMOD); + } + } + + if (javaBasePath == null || + !Files.exists(javaBasePath)) { + Log.error(String.format(I18N.getString( + "warning.no.jdk.modules.found"))); + } + + return modulePath; }); + // Returns the path to the JDK modules in the user defined module path. + private static Path findPathOfModule( List modulePath, String moduleName) { + + for (Path path : modulePath) { + Path moduleNamePath = path.resolve(moduleName); + + if (Files.exists(moduleNamePath)) { + return path; + } + } + + return null; + } + static final BundlerParamInfo MODULE = new BundlerParamInfo<>( Arguments.CLIOptions.MODULE.getId(), diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/model/ApplicationLaunchers.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/model/ApplicationLaunchers.java index ce2925d75e41c..af52696a54677 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/model/ApplicationLaunchers.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/model/ApplicationLaunchers.java @@ -57,12 +57,12 @@ public List asList() { }).orElseGet(List::of); } - public static Optional fromList(List launchers) { + public static Optional fromList(List launchers) { if (launchers == null || launchers.isEmpty()) { return Optional.empty(); } else { return Optional.of(new ApplicationLaunchers(launchers.getFirst(), - List.copyOf(launchers.subList(1, launchers.size())))); + launchers.subList(1, launchers.size()))); } } } diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/model/RuntimeBuilder.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/model/RuntimeBuilder.java index a0f5f077c700c..c989bcc8915a5 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/model/RuntimeBuilder.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/model/RuntimeBuilder.java @@ -24,7 +24,6 @@ */ package jdk.jpackage.internal.model; -import java.lang.module.ModuleFinder; import java.nio.file.Path; import java.util.List; @@ -47,13 +46,7 @@ public interface RuntimeBuilder { void create(AppImageLayout appImageLayout) throws PackagerException; /** - * Gets the default set of paths where jlink should look up for system Java - * modules. - * - *

    - * These paths are for {@code jlink} command. Using them with - * {@link ModuleFinder#of(Path...)} may not work as expected: attempt to find - * "java.base" module in these paths will fail. + * Gets the default set of paths where to find Java modules. * * @return the default set of paths where to find Java modules */ diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources.properties b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources.properties index 2a81b1c102cb2..3aa0c69dbd5be 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources.properties +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources.properties @@ -78,6 +78,8 @@ error.blocked.option=jlink option [{0}] is not permitted in --jlink-options error.no.name=Name not specified with --name and cannot infer one from app-image error.no.name.advice=Specify name with --name +warning.no.jdk.modules.found=Warning: No JDK Modules found + error.foreign-app-image=Error: Missing .jpackage.xml file in app-image dir "{0}" error.invalid-app-image=Error: app-image dir "{0}" generated by another jpackage version or malformed "{1}" file diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/FileUtils.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/FileUtils.java index cb1bcaa51b1af..8ac88c13e1d2c 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/FileUtils.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/FileUtils.java @@ -30,7 +30,6 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.SimpleFileVisitor; -import java.nio.file.StandardCopyOption; import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.List; @@ -107,17 +106,6 @@ private static boolean isPathMatch(Path what, List paths) { private static record CopyAction(Path src, Path dest) { void apply(CopyOption... options) throws IOException { - if (List.of(options).contains(StandardCopyOption.REPLACE_EXISTING)) { - // They requested copying with replacing the existing content. - if (src == null && Files.isRegularFile(dest)) { - // This copy action creates a directory, but a file at the same path already exists, so delete it. - Files.deleteIfExists(dest); - } else if (src != null && Files.isDirectory(dest)) { - // This copy action copies a file, but a directory at the same path exists already, so delete it. - deleteRecursive(dest); - } - } - if (src == null) { Files.createDirectories(dest); } else { diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/Result.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/Result.java index 8a61acafe777c..7bd6408183a41 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/Result.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/Result.java @@ -4,9 +4,7 @@ * * 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. + * 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 diff --git a/src/jdk.jpackage/unix/classes/jdk/jpackage/internal/PackageScripts.java b/src/jdk.jpackage/unix/classes/jdk/jpackage/internal/PackageScripts.java index cef5fe05f35dd..cd8799416f718 100644 --- a/src/jdk.jpackage/unix/classes/jdk/jpackage/internal/PackageScripts.java +++ b/src/jdk.jpackage/unix/classes/jdk/jpackage/internal/PackageScripts.java @@ -24,16 +24,15 @@ */ package jdk.jpackage.internal; -import static java.util.stream.Collectors.toMap; - import java.io.IOException; import java.io.UncheckedIOException; import java.nio.file.Path; import java.util.EnumSet; import java.util.Map; import java.util.Optional; -import java.util.TreeMap; import java.util.function.Supplier; +import java.util.function.UnaryOperator; +import java.util.stream.Collectors; import jdk.jpackage.internal.resources.ResourceLocator; /** @@ -47,11 +46,11 @@ static & Supplier> PackageScripts cre } PackageScripts(Class scriptIdsType) { - scripts = EnumSet.allOf(scriptIdsType).stream().collect(toMap(x -> x, scriptId -> { - return new ShellScriptResource(scriptId.name()).setResource(scriptId.get()); - }, (a, b) -> { - throw new UnsupportedOperationException(); - }, TreeMap::new)); + scripts = EnumSet.allOf(scriptIdsType).stream().collect( + Collectors.toMap(UnaryOperator.identity(), scriptId -> { + return new ShellScriptResource(scriptId.name()).setResource( + scriptId.get()); + })); } PackageScripts setSubstitutionData(T id, Map data) { diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinExeBundler.java b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinExeBundler.java index f61a26f0774f8..9ce758eb3c7d0 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinExeBundler.java +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinExeBundler.java @@ -65,7 +65,7 @@ public boolean isDefault() { @Override public boolean validate(Map params) throws ConfigException { - return msiBundler.validate(params, WinFromParams.EXE_PACKAGE); + return msiBundler.validate(params); } @Override diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinMsiBundler.java b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinMsiBundler.java index 24aa3e0573a7e..3ca26f38f8288 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinMsiBundler.java +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinMsiBundler.java @@ -30,7 +30,6 @@ import java.nio.file.Path; import java.util.Map; import jdk.jpackage.internal.model.ConfigException; -import jdk.jpackage.internal.model.Package; import jdk.jpackage.internal.model.PackagerException; import jdk.jpackage.internal.model.WinMsiPackage; import jdk.jpackage.internal.util.Result; @@ -81,15 +80,11 @@ public boolean isDefault() { } @Override - public boolean validate(Map params) throws ConfigException { - return validate(params, WinFromParams.MSI_PACKAGE); - } - - boolean validate(Map params, BundlerParamInfo pkgParam) + public boolean validate(Map params) throws ConfigException { try { // Order is important! - pkgParam.fetchFrom(params); + WinFromParams.APPLICATION.fetchFrom(params); BuildEnvFromParams.BUILD_ENV.fetchFrom(params); final var wixToolset = sysEnv.orElseThrow().wixToolset(); diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixAppImageFragmentBuilder.java b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixAppImageFragmentBuilder.java index 0dff5c26ae279..63be18a5ee8ae 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixAppImageFragmentBuilder.java +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixAppImageFragmentBuilder.java @@ -248,7 +248,7 @@ enum Id { String of(Path path) { if (this == Folder && KNOWN_DIRS.contains(path)) { - return path.getFileName().toString(); + return IOUtils.getFileName(path).toString(); } String result = of(path, prefix, name()); @@ -525,7 +525,7 @@ private String addShortcutComponent(XMLStreamWriter xml, Path launcherPath, } String launcherBasename = PathUtils.replaceSuffix( - launcherPath.getFileName(), "").toString(); + IOUtils.getFileName(launcherPath), "").toString(); Path shortcutPath = folder.getPath(this).resolve(launcherBasename); return addComponent(xml, shortcutPath, Component.Shortcut, unused -> { @@ -712,7 +712,7 @@ public void createDirectory(final Path dir) throws IOException { xml.writeAttribute("Id", Id.Folder.of(dir.getParent())); xml.writeStartElement("Directory"); xml.writeAttribute("Id", Id.Folder.of(dir)); - xml.writeAttribute("Name", dir.getFileName().toString()); + xml.writeAttribute("Name", IOUtils.getFileName(dir).toString()); xml.writeEndElement(); xml.writeEndElement(); } @@ -818,7 +818,7 @@ private void addIcons(XMLStreamWriter xml) throws appImagePathGroup.transform(installedAppImagePathGroup, new PathGroup.TransformHandler() { @Override public void copyFile(Path src, Path dst) throws IOException { - if (src.getFileName().toString().endsWith(".ico")) { + if (IOUtils.getFileName(src).toString().endsWith(".ico")) { icoFiles.add(Map.entry(src, dst)); } } diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixPipeline.java b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixPipeline.java index 4016019286203..be15b2028771a 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixPipeline.java +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixPipeline.java @@ -241,7 +241,7 @@ private void buildMsiWix3(Path msi) throws IOException { lightCmdline.addAll(lightOptions); wixObjs.stream().map(Path::toString).forEach(lightCmdline::add); - Files.createDirectories(msi.getParent()); + Files.createDirectories(IOUtils.getParent(msi)); execute(lightCmdline); } diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixSourceConverter.java b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixSourceConverter.java index b1ad973b9ed54..b07c525db2695 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixSourceConverter.java +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WixSourceConverter.java @@ -38,7 +38,6 @@ import java.util.HashMap; import java.util.Map; import java.util.Set; -import java.util.TreeMap; import java.util.function.Supplier; import java.util.stream.Collectors; import javax.xml.XMLConstants; @@ -145,7 +144,7 @@ Status applyTo(OverridableResource resource, Path resourceSaveAsFile) throws IOE newProxyInstance(XMLStreamWriter.class.getClassLoader(), new Class[]{XMLStreamWriter.class}, new NamespaceCleaner(nc. getPrefixToUri(), outputFactory.createXMLStreamWriter(outXml))))); - Files.createDirectories(resourceSaveAsFile.getParent()); + Files.createDirectories(IOUtils.getParent(resourceSaveAsFile)); Files.copy(new ByteArrayInputStream(outXml.toByteArray()), resourceSaveAsFile, StandardCopyOption.REPLACE_EXISTING); } catch (TransformerException | XMLStreamException ex) { @@ -194,7 +193,7 @@ void saveResources() throws IOException { } } - private final Map resources = new TreeMap<>(); + private final Map resources = new HashMap<>(); private final WixToolsetType wixToolsetType; } diff --git a/test/benchmarks/micros-javac/README.md b/test/benchmarks/micros-javac/README.md deleted file mode 100644 index 66ca073a7636f..0000000000000 --- a/test/benchmarks/micros-javac/README.md +++ /dev/null @@ -1,61 +0,0 @@ -# Javac microbenchmarks - -The Javac Microbenchmarks is a collection of microbenchmarks for measuring -the performance of Javac API using the -[JMH](http://openjdk.java.net/projects/code-tools/jmh/) framework. - - -## Building and running the project - -Currently, the project can be built and run with JDK 9 and later. This is -a Maven project and is built by: - - $ mvn clean install - -After building, the executable jar is target/micros-javac-[version].jar. -Run the benchmarks with: - - $ java -jar target/micros-javac-*.jar [optional jmh parameters] - -See the entire list of benchmarks using: - - $ java -jar target/micros-javacs-*.jar -l [optional regex to select benchmarks] - -For example: - - $ java -jar target/micros-javac-1.0-SNAPSHOT.jar -l - Benchmarks: - org.openjdk.bench.langtools.javac.GroupJavacBenchmark.coldGroup - org.openjdk.bench.langtools.javac.GroupJavacBenchmark.hotGroup - org.openjdk.bench.langtools.javac.SingleJavacBenchmark.compileCold - org.openjdk.bench.langtools.javac.SingleJavacBenchmark.compileHot - -And the same regex syntax works to run some test: - - $ java -jar target/micros-javac-1.0-SNAPSHOT.jar SingleJavacBenchmark.compileHot - -## Troubleshooting - -### Build of micros-javac module got stuck - -If you build got stuck on `[get] Getting: https://download.java.net/openjdk/jdk11/ri/openjdk-11+28_windows-x64_bin.zip` then you are probably experiencing some networking or web proxy obstacles. - -One solution is to download required reference JDK from [https://download.java.net/openjdk/jdk11/ri/openjdk-11+28_windows-x64_bin.zip](https://download.java.net/openjdk/jdk11/ri/openjdk-11+28_windows-x64_bin.zip) manually and then build the project with property pointing to the local copy: - - $ mvn clean install -Djavac.benchmark.openjdk.zip.download.url=file:////openjdk-11+28_windows-x64_bin.zip - -Note: Please use `openjdk-11+28_windows-x64_bin.zip` to build the project no matter what target platform is. - -Another solution might be to add proxy settings: - - $ mvn -Dhttps.proxyHost=... -Dhttps.proxyPort=... clean install - -### Execution of micros-javac benchmarks takes several hours - -micros-javac benchmarks consist of two sets of benchmarks: - * `SingleJavacBenchmark` (which is parametrized) measures each single javac compilation stage in an isolated run. This benchmark is designed for exact automated performance regression testing and it takes several hours to execute completely. - * `GroupJavacBenchmark` is grouping the measurements of all javac compilation stages into one run and its execution should take less than 30 minutes on a regular developers computer. - -Solution to speed up javac benchmarking is to select only `GroupJavacBenchmark` for execution using following command line: - - $ java -jar target/micros-javac-1.0-SNAPSHOT.jar .*GroupJavacBenchmark.* diff --git a/test/benchmarks/micros-javac/pom.xml b/test/benchmarks/micros-javac/pom.xml deleted file mode 100644 index 5a8a40d7a9afc..0000000000000 --- a/test/benchmarks/micros-javac/pom.xml +++ /dev/null @@ -1,139 +0,0 @@ - - - 4.0.0 - org.openjdk - micros-javac - jar - 1.0-SNAPSHOT - OpenJDK Microbenchmark of Java Compile - - https://download.java.net/openjdk/jdk11/ri/openjdk-11+28_windows-x64_bin.zip - UTF-8 - 1.36 - - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.6.1 - - - package - - shade - - - - - org.openjdk.jmh.Main - - - META-INF/BenchmarkList - - - META-INF/CompilerHints - - - false - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.14.1 - - 1.8 - 1.8 - - - org.openjdk.jmh - jmh-generator-annprocess - ${jmh.version} - - - - - - org.apache.maven.plugins - maven-release-plugin - 3.1.1 - - - maven-deploy-plugin - 3.1.4 - - - maven-antrun-plugin - 3.1.0 - - - process-resources - - - - - - - - - - - - - -------------------------------------------------- -Bundling JDK sources with following release info: -------------------------------------------------- -${release.info} -------------------------------------------------- - - - - - run - - - - - - - - - - org.openjdk.jmh - jmh-core - ${jmh.version} - - - org.openjdk.jmh - jmh-generator-annprocess - ${jmh.version} - provided - - - diff --git a/test/benchmarks/micros-javac/src/main/java/org/openjdk/bench/langtools/javac/GroupJavacBenchmark.java b/test/benchmarks/micros-javac/src/main/java/org/openjdk/bench/langtools/javac/GroupJavacBenchmark.java deleted file mode 100644 index 5ca3f0bf6483a..0000000000000 --- a/test/benchmarks/micros-javac/src/main/java/org/openjdk/bench/langtools/javac/GroupJavacBenchmark.java +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright (c) 2020, 2021, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.openjdk.bench.langtools.javac; - -import java.io.IOException; -import java.util.concurrent.TimeUnit; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.BenchmarkMode; -import org.openjdk.jmh.annotations.Fork; -import org.openjdk.jmh.annotations.Group; -import org.openjdk.jmh.annotations.Measurement; -import org.openjdk.jmh.annotations.Mode; -import org.openjdk.jmh.annotations.OutputTimeUnit; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.Warmup; -import org.openjdk.jmh.infra.Blackhole; - -@State(Scope.Benchmark) -public class GroupJavacBenchmark extends JavacBenchmark { - - public static final String COLD_GROUP_NAME = "coldGroup"; - public static final int COLD_ITERATION_WARMUPS = 0; - public static final int COLD_ITERATIONS = 1; - public static final int COLD_FORK_WARMUPS = 1; - public static final int COLD_FORKS = 15; - - public static final String HOT_GROUP_NAME = "hotGroup"; - public static final int HOT_ITERATION_WARMUPS = 8; - public static final int HOT_ITERATIONS = 10; - public static final int HOT_FORK_WARMUPS = 0; - public static final int HOT_FORKS = 1; - - @Benchmark - @Group(COLD_GROUP_NAME) - @BenchmarkMode(Mode.SingleShotTime) - @Warmup(iterations = COLD_ITERATION_WARMUPS) - @Measurement(iterations = COLD_ITERATIONS) - @Fork(warmups = COLD_FORK_WARMUPS, value = COLD_FORKS, jvmArgsPrepend = { "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" }) - @OutputTimeUnit(TimeUnit.SECONDS) - public void cold1_Init() throws InterruptedException { - Stage.Init.waitFor(); - } - - @Benchmark - @Group(COLD_GROUP_NAME) - @BenchmarkMode(Mode.SingleShotTime) - @Warmup(iterations = COLD_ITERATION_WARMUPS) - @Measurement(iterations = COLD_ITERATIONS) - @Fork(warmups = COLD_FORK_WARMUPS, value = COLD_FORKS, jvmArgsPrepend = { "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" }) - @OutputTimeUnit(TimeUnit.SECONDS) - public void cold2_Parse() throws InterruptedException { - Stage.Parse.waitFor(); - } - - @Benchmark - @Group(COLD_GROUP_NAME) - @BenchmarkMode(Mode.SingleShotTime) - @Warmup(iterations = COLD_ITERATION_WARMUPS) - @Measurement(iterations = COLD_ITERATIONS) - @Fork(warmups = COLD_FORK_WARMUPS, value = COLD_FORKS, jvmArgsPrepend = { "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" }) - @OutputTimeUnit(TimeUnit.SECONDS) - public void cold3_InitModules() throws InterruptedException { - Stage.InitModules.waitFor(); - } - - @Benchmark - @Group(COLD_GROUP_NAME) - @BenchmarkMode(Mode.SingleShotTime) - @Warmup(iterations = COLD_ITERATION_WARMUPS) - @Measurement(iterations = COLD_ITERATIONS) - @Fork(warmups = COLD_FORK_WARMUPS, value = COLD_FORKS, jvmArgsPrepend = { "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" }) - @OutputTimeUnit(TimeUnit.SECONDS) - public void cold4_Enter() throws InterruptedException { - Stage.Enter.waitFor(); - } - - @Benchmark - @Group(COLD_GROUP_NAME) - @BenchmarkMode(Mode.SingleShotTime) - @Warmup(iterations = COLD_ITERATION_WARMUPS) - @Measurement(iterations = COLD_ITERATIONS) - @Fork(warmups = COLD_FORK_WARMUPS, value = COLD_FORKS, jvmArgsPrepend = { "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" }) - @OutputTimeUnit(TimeUnit.SECONDS) - public void cold5_Attribute() throws InterruptedException { - Stage.Attribute.waitFor(); - } - - @Benchmark - @Group(COLD_GROUP_NAME) - @BenchmarkMode(Mode.SingleShotTime) - @Warmup(iterations = COLD_ITERATION_WARMUPS) - @Measurement(iterations = COLD_ITERATIONS) - @Fork(warmups = COLD_FORK_WARMUPS, value = COLD_FORKS, jvmArgsPrepend = { "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" }) - @OutputTimeUnit(TimeUnit.SECONDS) - public void cold6_Flow() throws InterruptedException { - Stage.Flow.waitFor(); - } - - @Benchmark - @Group(COLD_GROUP_NAME) - @BenchmarkMode(Mode.SingleShotTime) - @Warmup(iterations = COLD_ITERATION_WARMUPS) - @Measurement(iterations = COLD_ITERATIONS) - @Fork(warmups = COLD_FORK_WARMUPS, value = COLD_FORKS, jvmArgsPrepend = { "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" }) - @OutputTimeUnit(TimeUnit.SECONDS) - public void cold7_Desugar() throws InterruptedException { - Stage.Desugar.waitFor(); - } - - @Benchmark - @Group(COLD_GROUP_NAME) - @BenchmarkMode(Mode.SingleShotTime) - @Warmup(iterations = COLD_ITERATION_WARMUPS) - @Measurement(iterations = COLD_ITERATIONS) - @Fork(warmups = COLD_FORK_WARMUPS, value = COLD_FORKS, jvmArgsPrepend = { "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" }) - @OutputTimeUnit(TimeUnit.SECONDS) - public void cold8_Generate(Blackhole bh) throws IOException { - compile(bh, Stage.Generate); - } - - @Benchmark - @Group(HOT_GROUP_NAME) - @BenchmarkMode(Mode.SingleShotTime) - @Warmup(iterations = HOT_ITERATION_WARMUPS) - @Measurement(iterations = HOT_ITERATIONS) - @Fork(warmups = HOT_FORK_WARMUPS, value = HOT_FORKS, jvmArgsPrepend = { "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" }) - @OutputTimeUnit(TimeUnit.SECONDS) - public void hot1_Init() throws InterruptedException { - Stage.Init.waitFor(); - } - - @Benchmark - @Group(HOT_GROUP_NAME) - @BenchmarkMode(Mode.SingleShotTime) - @Warmup(iterations = HOT_ITERATION_WARMUPS) - @Measurement(iterations = HOT_ITERATIONS) - @Fork(warmups = HOT_FORK_WARMUPS, value = HOT_FORKS, jvmArgsPrepend = { "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" }) - @OutputTimeUnit(TimeUnit.SECONDS) - public void hot2_Parse() throws InterruptedException { - Stage.Parse.waitFor(); - } - - @Benchmark - @Group(HOT_GROUP_NAME) - @BenchmarkMode(Mode.SingleShotTime) - @Warmup(iterations = HOT_ITERATION_WARMUPS) - @Measurement(iterations = HOT_ITERATIONS) - @Fork(warmups = HOT_FORK_WARMUPS, value = HOT_FORKS, jvmArgsPrepend = { "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" }) - @OutputTimeUnit(TimeUnit.SECONDS) - public void hot3_InitModules() throws InterruptedException { - Stage.InitModules.waitFor(); - } - - @Benchmark - @Group(HOT_GROUP_NAME) - @BenchmarkMode(Mode.SingleShotTime) - @Warmup(iterations = HOT_ITERATION_WARMUPS) - @Measurement(iterations = HOT_ITERATIONS) - @Fork(warmups = HOT_FORK_WARMUPS, value = HOT_FORKS, jvmArgsPrepend = { "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" }) - @OutputTimeUnit(TimeUnit.SECONDS) - public void hot4_Enter() throws InterruptedException { - Stage.Enter.waitFor(); - } - - @Benchmark - @Group(HOT_GROUP_NAME) - @BenchmarkMode(Mode.SingleShotTime) - @Warmup(iterations = HOT_ITERATION_WARMUPS) - @Measurement(iterations = HOT_ITERATIONS) - @Fork(warmups = HOT_FORK_WARMUPS, value = HOT_FORKS, jvmArgsPrepend = { "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" }) - @OutputTimeUnit(TimeUnit.SECONDS) - public void hot5_Attribute() throws InterruptedException { - Stage.Attribute.waitFor(); - } - - @Benchmark - @Group(HOT_GROUP_NAME) - @BenchmarkMode(Mode.SingleShotTime) - @Warmup(iterations = HOT_ITERATION_WARMUPS) - @Measurement(iterations = HOT_ITERATIONS) - @Fork(warmups = HOT_FORK_WARMUPS, value = HOT_FORKS, jvmArgsPrepend = { "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" }) - @OutputTimeUnit(TimeUnit.SECONDS) - public void hot6_Flow() throws InterruptedException { - Stage.Flow.waitFor(); - } - - @Benchmark - @Group(HOT_GROUP_NAME) - @BenchmarkMode(Mode.SingleShotTime) - @Warmup(iterations = HOT_ITERATION_WARMUPS) - @Measurement(iterations = HOT_ITERATIONS) - @Fork(warmups = HOT_FORK_WARMUPS, value = HOT_FORKS, jvmArgsPrepend = { "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" }) - @OutputTimeUnit(TimeUnit.SECONDS) - public void hot7_Desugar() throws InterruptedException { - Stage.Desugar.waitFor(); - } - - @Benchmark - @Group(HOT_GROUP_NAME) - @BenchmarkMode(Mode.SingleShotTime) - @Warmup(iterations = HOT_ITERATION_WARMUPS) - @Measurement(iterations = HOT_ITERATIONS) - @Fork(warmups = HOT_FORK_WARMUPS, value = HOT_FORKS, jvmArgsPrepend = { "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" }) - @OutputTimeUnit(TimeUnit.SECONDS) - public void hot8_Generate(Blackhole bh) throws IOException { - compile(bh, Stage.Generate); - } -} diff --git a/test/benchmarks/micros-javac/src/main/java/org/openjdk/bench/langtools/javac/JavacBenchmark.java b/test/benchmarks/micros-javac/src/main/java/org/openjdk/bench/langtools/javac/JavacBenchmark.java deleted file mode 100644 index 1afffc6d0442f..0000000000000 --- a/test/benchmarks/micros-javac/src/main/java/org/openjdk/bench/langtools/javac/JavacBenchmark.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright (c) 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.openjdk.bench.langtools.javac; - -import com.sun.tools.javac.comp.AttrContext; -import com.sun.tools.javac.comp.Env; -import com.sun.tools.javac.file.JavacFileManager; -import com.sun.tools.javac.main.JavaCompiler; -import com.sun.tools.javac.main.Main; -import com.sun.tools.javac.tree.JCTree; -import com.sun.tools.javac.util.Context; -import com.sun.tools.javac.util.Context.Factory; -import com.sun.tools.javac.util.List; -import com.sun.tools.javac.util.ListBuffer; -import com.sun.tools.javac.util.Pair; -import java.io.BufferedInputStream; -import java.io.File; -import java.io.IOException; -import java.io.OutputStream; -import java.io.PrintStream; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Comparator; -import java.util.Queue; -import static java.util.logging.Level.FINE; -import static java.util.logging.Level.CONFIG; -import java.util.logging.Logger; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; -import javax.tools.FileObject; -import javax.tools.ForwardingJavaFileObject; -import javax.tools.JavaFileManager; -import javax.tools.JavaFileObject; -import org.openjdk.jmh.annotations.Level; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.Setup; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.TearDown; -import org.openjdk.jmh.infra.Blackhole; - -@State(Scope.Benchmark) -public class JavacBenchmark { - - static final Logger LOG = Logger.getLogger(JavacBenchmark.class.getName()); - - public enum Stage { - Init, Parse, InitModules, Enter, Attribute, Flow, Desugar, Generate; - - public synchronized void waitFor() throws InterruptedException { - wait(); - } - public synchronized void notifyDone() { - notifyAll(); - LOG.log(FINE, "{0} finished.", this.name()); - } - public boolean isAfter(Stage other) { - return ordinal() > other.ordinal(); - } - } - - private Path root; - private Path srcList; - - @Setup(Level.Trial) - public void setup(Blackhole bh) throws IOException, InterruptedException { - LOG.log(CONFIG, "Release info of the sources to be compiled by the benchmark:\n{0}", new String(JavacBenchmark.class.getResourceAsStream("/release").readAllBytes(), StandardCharsets.UTF_8)); - root = Files.createTempDirectory("JavacBenchmarkRoot"); - srcList = root.resolve("sources.list"); - int i = 0; - try (PrintStream srcListOut = new PrintStream(srcList.toFile())) { - try (ZipInputStream zis = new ZipInputStream(new BufferedInputStream(JavacBenchmark.class.getResourceAsStream("/src.zip")))) { - for (ZipEntry entry; (entry = zis.getNextEntry()) != null;) { - final String ename = entry.getName(); - if (!ename.startsWith("java.desktop") && !ename.startsWith("jdk.internal.vm.compiler") && !ename.startsWith("jdk.aot") && !ename.startsWith("jdk.accessibility")) { - if (!entry.isDirectory() && ename.endsWith(".java")) { - Path dst = root.resolve(ename); - Files.createDirectories(dst.getParent()); - Files.copy(zis, dst); - Files.readAllBytes(dst); //reads all the file back to exclude antivirus scanning time from following measurements - srcListOut.println(dst.toString()); - i++; - } - } - } - } - } - Files.walk(root).map(Path::toFile).forEach(File::deleteOnExit); //mark all files and folders for deletion on JVM exit for cases when tearDown is not executed - Thread.sleep(10000); //give some more time for the system to catch a breath for more precise measurement - LOG.log(FINE, "Extracted {0} sources.", i); - } - - @TearDown(Level.Trial) - public void tearDown() throws IOException { - Files.walk(root).sorted(Comparator.reverseOrder()).map(Path::toFile).forEachOrdered(File::delete); - LOG.fine("Sources deleted."); - } - - protected void compile(Blackhole bh, final Stage stopAt) throws IOException { - final OutputStream bhos = new OutputStream() { - @Override - public void write(int b) throws IOException { - bh.consume(b); - } - @Override - public void write(byte[] b, int off, int len) throws IOException { - bh.consume(b); - } - }; - final Context ctx = new Context(); - //inject JavaCompiler wrapping all measured methods so they directly report to the benchmark - ctx.put(JavaCompiler.compilerKey, (Factory)(c) -> { - return new JavaCompiler(c) { - @Override - public List parseFiles(Iterable fileObjects) { - Stage.Init.notifyDone(); - return stopAt.isAfter(Stage.Init) ? super.parseFiles(fileObjects) : List.nil(); - } - - @Override - public List initModules(List roots) { - Stage.Parse.notifyDone(); - return stopAt.isAfter(Stage.Parse) ? super.initModules(roots) : List.nil(); - } - - @Override - public List enterTrees(List roots) { - Stage.InitModules.notifyDone(); - return stopAt.isAfter(Stage.InitModules) ? super.enterTrees(roots) : List.nil(); - } - - @Override - public Queue> attribute(Queue> envs) { - Stage.Enter.notifyDone(); - return stopAt.isAfter(Stage.Enter) ? super.attribute(envs) : new ListBuffer<>(); - } - - @Override - public Queue> flow(Queue> envs) { - Stage.Attribute.notifyDone(); - return stopAt.isAfter(Stage.Attribute) ? super.flow(envs) : new ListBuffer<>(); - } - - @Override - public Queue, JCTree.JCClassDecl>> desugar(Queue> envs) { - Stage.Flow.notifyDone(); - return stopAt.isAfter(Stage.Flow) ? super.desugar(envs) : new ListBuffer<>(); - } - - @Override - public void generate(Queue, JCTree.JCClassDecl>> queue) { - Stage.Desugar.notifyDone(); - if (stopAt.isAfter(Stage.Desugar)) super.generate(queue); - } - }; - }); - //JavaFileManager directing all writes to a Blackhole to avoid measurement fluctuations due to delayed filesystem writes - try (JavacFileManager mngr = new JavacFileManager(ctx, true, null) { - @Override - public JavaFileObject getJavaFileForOutput(JavaFileManager.Location arg0, String arg1, JavaFileObject.Kind arg2, FileObject arg3) throws IOException { - return new ForwardingJavaFileObject(super.getJavaFileForOutput(arg0, arg1, arg2, arg3)) { - @Override - public OutputStream openOutputStream() throws IOException { - return bhos; - } - }; - } - }) { - String[] cmdLine = new String[] {"-XDcompilePolicy=simple", "-implicit:none", "-nowarn", "--module-source-path", root.toString(), "-d", root.toString(), "-XDignore.symbol.file=true", "@" + srcList.toString()}; - if (new Main("javac").compile(cmdLine, ctx).exitCode != 0) { - throw new IOException("compilation failed"); - } - } - LOG.fine("Compilation finished."); - } -} diff --git a/test/benchmarks/micros-javac/src/main/java/org/openjdk/bench/langtools/javac/SingleJavacBenchmark.java b/test/benchmarks/micros-javac/src/main/java/org/openjdk/bench/langtools/javac/SingleJavacBenchmark.java deleted file mode 100644 index 2cc5c1a7c83eb..0000000000000 --- a/test/benchmarks/micros-javac/src/main/java/org/openjdk/bench/langtools/javac/SingleJavacBenchmark.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2020, 2021, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package org.openjdk.bench.langtools.javac; - -import java.io.IOException; -import java.util.concurrent.TimeUnit; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.BenchmarkMode; -import org.openjdk.jmh.annotations.Fork; -import org.openjdk.jmh.annotations.Measurement; -import org.openjdk.jmh.annotations.Mode; -import org.openjdk.jmh.annotations.OutputTimeUnit; -import org.openjdk.jmh.annotations.Param; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.Threads; -import org.openjdk.jmh.annotations.Warmup; -import org.openjdk.jmh.infra.Blackhole; - -@State(Scope.Benchmark) -public class SingleJavacBenchmark extends JavacBenchmark { - - @Param - public Stage stopStage; - - @Benchmark - @Threads(1) - @BenchmarkMode(Mode.SingleShotTime) - @Warmup(iterations = 0) - @Measurement(iterations = 1) - @Fork(warmups = 1, value = 15, jvmArgsPrepend = { "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" }) - @OutputTimeUnit(TimeUnit.SECONDS) - public void compileCold(Blackhole bh) throws IOException { - compile(bh, stopStage); - } - - @Benchmark - @Threads(1) - @BenchmarkMode(Mode.SingleShotTime) - @Warmup(iterations = 8) - @Measurement(iterations = 10) - @Fork(warmups = 0, value = 1, jvmArgsPrepend = { "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED", "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" }) - @OutputTimeUnit(TimeUnit.SECONDS) - public void compileHot(Blackhole bh) throws IOException { - compile(bh, stopStage); - } -} diff --git a/test/docs/ProblemList.txt b/test/docs/ProblemList.txt index 83693eacbd111..914ae21d49fae 100644 --- a/test/docs/ProblemList.txt +++ b/test/docs/ProblemList.txt @@ -1,6 +1,6 @@ ########################################################################### # -# Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -39,5 +39,3 @@ # More than one label is allowed but must be on the same line. # ############################################################################# - -jdk/javadoc/doccheck/checks/jdkCheckLinks.java 8370249 generic-all diff --git a/test/hotspot/gtest/aarch64/aarch64-asmtest.py b/test/hotspot/gtest/aarch64/aarch64-asmtest.py index 48b19acaa059b..bf4f2111999bd 100644 --- a/test/hotspot/gtest/aarch64/aarch64-asmtest.py +++ b/test/hotspot/gtest/aarch64/aarch64-asmtest.py @@ -2143,10 +2143,6 @@ def generate(kind, names): ["facge", "__ sve_fac(Assembler::GE, p1, __ H, p2, z4, z5);", "facge\tp1.h, p2/z, z4.h, z5.h"], ["facge", "__ sve_fac(Assembler::GE, p1, __ S, p2, z4, z5);", "facge\tp1.s, p2/z, z4.s, z5.s"], ["facge", "__ sve_fac(Assembler::GE, p1, __ D, p2, z4, z5);", "facge\tp1.d, p2/z, z4.d, z5.d"], - ["splice", "__ sve_splice(z0, __ B, p0, z1);", "splice\tz0.b, p0, z0.b, z1.b"], - ["splice", "__ sve_splice(z0, __ H, p0, z1);", "splice\tz0.h, p0, z0.h, z1.h"], - ["splice", "__ sve_splice(z0, __ S, p0, z1);", "splice\tz0.s, p0, z0.s, z1.s"], - ["splice", "__ sve_splice(z0, __ D, p0, z1);", "splice\tz0.d, p0, z0.d, z1.d"], # SVE2 instructions ["histcnt", "__ sve_histcnt(z16, __ S, p0, z16, z16);", "histcnt\tz16.s, p0/z, z16.s, z16.s"], ["histcnt", "__ sve_histcnt(z17, __ D, p0, z17, z17);", "histcnt\tz17.d, p0/z, z17.d, z17.d"], diff --git a/test/hotspot/gtest/aarch64/asmtest.out.h b/test/hotspot/gtest/aarch64/asmtest.out.h index 34a5f8ca68e94..352ea33750ee0 100644 --- a/test/hotspot/gtest/aarch64/asmtest.out.h +++ b/test/hotspot/gtest/aarch64/asmtest.out.h @@ -1156,10 +1156,6 @@ __ sve_fac(Assembler::GE, p1, __ H, p2, z4, z5); // facge p1.h, p2/z, z4.h, z5.h __ sve_fac(Assembler::GE, p1, __ S, p2, z4, z5); // facge p1.s, p2/z, z4.s, z5.s __ sve_fac(Assembler::GE, p1, __ D, p2, z4, z5); // facge p1.d, p2/z, z4.d, z5.d - __ sve_splice(z0, __ B, p0, z1); // splice z0.b, p0, z0.b, z1.b - __ sve_splice(z0, __ H, p0, z1); // splice z0.h, p0, z0.h, z1.h - __ sve_splice(z0, __ S, p0, z1); // splice z0.s, p0, z0.s, z1.s - __ sve_splice(z0, __ D, p0, z1); // splice z0.d, p0, z0.d, z1.d __ sve_histcnt(z16, __ S, p0, z16, z16); // histcnt z16.s, p0/z, z16.s, z16.s __ sve_histcnt(z17, __ D, p0, z17, z17); // histcnt z17.d, p0/z, z17.d, z17.d @@ -1449,30 +1445,30 @@ 0x9101a1a0, 0xb10a5cc8, 0xd10810aa, 0xf10fd061, 0x120cb166, 0x321764bc, 0x52174681, 0x720c0227, 0x9241018e, 0xb25a2969, 0xd278b411, 0xf26aad01, - 0x14000000, 0x17ffffd7, 0x140004bb, 0x94000000, - 0x97ffffd4, 0x940004b8, 0x3400000a, 0x34fffa2a, - 0x340096aa, 0x35000008, 0x35fff9c8, 0x35009648, - 0xb400000b, 0xb4fff96b, 0xb40095eb, 0xb500001d, - 0xb5fff91d, 0xb500959d, 0x10000013, 0x10fff8b3, - 0x10009533, 0x90000013, 0x36300016, 0x3637f836, - 0x363094b6, 0x3758000c, 0x375ff7cc, 0x3758944c, + 0x14000000, 0x17ffffd7, 0x140004b7, 0x94000000, + 0x97ffffd4, 0x940004b4, 0x3400000a, 0x34fffa2a, + 0x3400962a, 0x35000008, 0x35fff9c8, 0x350095c8, + 0xb400000b, 0xb4fff96b, 0xb400956b, 0xb500001d, + 0xb5fff91d, 0xb500951d, 0x10000013, 0x10fff8b3, + 0x100094b3, 0x90000013, 0x36300016, 0x3637f836, + 0x36309436, 0x3758000c, 0x375ff7cc, 0x375893cc, 0x128313a0, 0x528a32c7, 0x7289173b, 0x92ab3acc, 0xd2a0bf94, 0xf2c285e8, 0x9358722f, 0x330e652f, 0x53067f3b, 0x93577c53, 0xb34a1aac, 0xd35a4016, 0x13946c63, 0x93c3dbc8, 0x54000000, 0x54fff5a0, - 0x54009220, 0x54000001, 0x54fff541, 0x540091c1, - 0x54000002, 0x54fff4e2, 0x54009162, 0x54000002, - 0x54fff482, 0x54009102, 0x54000003, 0x54fff423, - 0x540090a3, 0x54000003, 0x54fff3c3, 0x54009043, - 0x54000004, 0x54fff364, 0x54008fe4, 0x54000005, - 0x54fff305, 0x54008f85, 0x54000006, 0x54fff2a6, - 0x54008f26, 0x54000007, 0x54fff247, 0x54008ec7, - 0x54000008, 0x54fff1e8, 0x54008e68, 0x54000009, - 0x54fff189, 0x54008e09, 0x5400000a, 0x54fff12a, - 0x54008daa, 0x5400000b, 0x54fff0cb, 0x54008d4b, - 0x5400000c, 0x54fff06c, 0x54008cec, 0x5400000d, - 0x54fff00d, 0x54008c8d, 0x5400000e, 0x54ffefae, - 0x54008c2e, 0x5400000f, 0x54ffef4f, 0x54008bcf, + 0x540091a0, 0x54000001, 0x54fff541, 0x54009141, + 0x54000002, 0x54fff4e2, 0x540090e2, 0x54000002, + 0x54fff482, 0x54009082, 0x54000003, 0x54fff423, + 0x54009023, 0x54000003, 0x54fff3c3, 0x54008fc3, + 0x54000004, 0x54fff364, 0x54008f64, 0x54000005, + 0x54fff305, 0x54008f05, 0x54000006, 0x54fff2a6, + 0x54008ea6, 0x54000007, 0x54fff247, 0x54008e47, + 0x54000008, 0x54fff1e8, 0x54008de8, 0x54000009, + 0x54fff189, 0x54008d89, 0x5400000a, 0x54fff12a, + 0x54008d2a, 0x5400000b, 0x54fff0cb, 0x54008ccb, + 0x5400000c, 0x54fff06c, 0x54008c6c, 0x5400000d, + 0x54fff00d, 0x54008c0d, 0x5400000e, 0x54ffefae, + 0x54008bae, 0x5400000f, 0x54ffef4f, 0x54008b4f, 0xd40658e1, 0xd4014d22, 0xd4046543, 0xd4273f60, 0xd44cad80, 0xd503201f, 0xd503203f, 0xd503205f, 0xd503209f, 0xd50320bf, 0xd503219f, 0xd50323bf, @@ -1693,8 +1689,7 @@ 0x05a14c00, 0x05e14c00, 0x05304001, 0x05314001, 0x05a18610, 0x05e18610, 0x0420bc31, 0x05271e11, 0x6545e891, 0x6585e891, 0x65c5e891, 0x6545c891, - 0x6585c891, 0x65c5c891, 0x052c8020, 0x056c8020, - 0x05ac8020, 0x05ec8020, 0x45b0c210, 0x45f1c231, + 0x6585c891, 0x65c5c891, 0x45b0c210, 0x45f1c231, 0x1e601000, 0x1e603000, 0x1e621000, 0x1e623000, 0x1e641000, 0x1e643000, 0x1e661000, 0x1e663000, 0x1e681000, 0x1e683000, 0x1e6a1000, 0x1e6a3000, diff --git a/test/hotspot/gtest/nmt/test_nmt_buffer_overflow_detection.cpp b/test/hotspot/gtest/nmt/test_nmt_buffer_overflow_detection.cpp index 5752d6df75d9d..ae3f4e7451656 100644 --- a/test/hotspot/gtest/nmt/test_nmt_buffer_overflow_detection.cpp +++ b/test/hotspot/gtest/nmt/test_nmt_buffer_overflow_detection.cpp @@ -23,7 +23,6 @@ */ #include "memory/allocation.hpp" -#include "memory/arena.hpp" #include "nmt/memTracker.hpp" #include "runtime/os.hpp" #include "sanitizers/address.hpp" @@ -143,21 +142,6 @@ DEFINE_TEST(test_corruption_on_realloc_growing, COMMON_NMT_HEAP_CORRUPTION_MESSA static void test_corruption_on_realloc_shrinking() { test_corruption_on_realloc(0x11, 0x10); } DEFINE_TEST(test_corruption_on_realloc_shrinking, COMMON_NMT_HEAP_CORRUPTION_MESSAGE_PREFIX); -static void test_chunkpool_lock() { - if (!MemTracker::enabled()) { - tty->print_cr("Skipped"); - return; - } - PrintNMTStatistics = true; - { - ChunkPoolLocker cpl; - char* mem = (char*)os::malloc(100, mtTest); - memset(mem - 16, 0, 100 + 16 + 2); - os::free(mem); - } -} -DEFINE_TEST(test_chunkpool_lock, COMMON_NMT_HEAP_CORRUPTION_MESSAGE_PREFIX); - /////// // realloc is the trickiest of the bunch. Test that realloc works and correctly takes over @@ -180,14 +164,4 @@ TEST_VM(NMT, test_realloc) { } } -TEST_VM_FATAL_ERROR_MSG(NMT, memory_corruption_call_stack, ".*header canary.*") { - if (MemTracker::tracking_level() != NMT_detail) { - guarantee(false, "fake message ignore this - header canary"); - } - const size_t SIZE = 1024; - char* p = (char*)os::malloc(SIZE, mtTest); - *(p - 1) = 0; - os::free(p); -} - #endif // !INCLUDE_ASAN diff --git a/test/hotspot/gtest/opto/test_regmask.cpp b/test/hotspot/gtest/opto/test_regmask.cpp index f367ca4bef42b..0975314c33d09 100644 --- a/test/hotspot/gtest/opto/test_regmask.cpp +++ b/test/hotspot/gtest/opto/test_regmask.cpp @@ -33,11 +33,11 @@ static void contains_expected_num_of_registers(const RegMask& rm, unsigned int expected) { - ASSERT_TRUE(rm.size() == expected); + ASSERT_TRUE(rm.Size() == expected); if (expected > 0) { - ASSERT_TRUE(!rm.is_empty()); + ASSERT_TRUE(!rm.is_Empty()); } else { - ASSERT_TRUE(rm.is_empty()); + ASSERT_TRUE(rm.is_Empty()); ASSERT_TRUE(!rm.is_infinite_stack()); } @@ -60,14 +60,14 @@ TEST_VM(RegMask, empty) { TEST_VM(RegMask, iteration) { RegMask rm; - rm.insert(30); - rm.insert(31); - rm.insert(32); - rm.insert(33); - rm.insert(62); - rm.insert(63); - rm.insert(64); - rm.insert(65); + rm.Insert(30); + rm.Insert(31); + rm.Insert(32); + rm.Insert(33); + rm.Insert(62); + rm.Insert(63); + rm.Insert(64); + rm.Insert(65); RegMaskIterator rmi(rm); ASSERT_TRUE(rmi.next() == OptoReg::Name(30)); @@ -82,12 +82,12 @@ TEST_VM(RegMask, iteration) { } TEST_VM(RegMask, Set_ALL) { - // Check that set_all doesn't add bits outside of rm.rm_size_bits() + // Check that Set_All doesn't add bits outside of rm.rm_size_bits() RegMask rm; - rm.set_all(); - ASSERT_TRUE(rm.size() == rm.rm_size_in_bits()); - ASSERT_TRUE(!rm.is_empty()); - // set_all sets infinite_stack + rm.Set_All(); + ASSERT_TRUE(rm.Size() == rm.rm_size_in_bits()); + ASSERT_TRUE(!rm.is_Empty()); + // Set_All sets infinite_stack ASSERT_TRUE(rm.is_infinite_stack()); contains_expected_num_of_registers(rm, rm.rm_size_in_bits()); } @@ -95,64 +95,64 @@ TEST_VM(RegMask, Set_ALL) { TEST_VM(RegMask, Clear) { // Check that Clear doesn't leave any stray bits RegMask rm; - rm.set_all(); - rm.clear(); + rm.Set_All(); + rm.Clear(); contains_expected_num_of_registers(rm, 0); } -TEST_VM(RegMask, and_with) { +TEST_VM(RegMask, AND) { RegMask rm1; - rm1.insert(OptoReg::Name(1)); + rm1.Insert(OptoReg::Name(1)); contains_expected_num_of_registers(rm1, 1); - ASSERT_TRUE(rm1.member(OptoReg::Name(1))); + ASSERT_TRUE(rm1.Member(OptoReg::Name(1))); - rm1.and_with(rm1); + rm1.AND(rm1); contains_expected_num_of_registers(rm1, 1); RegMask rm2; - rm1.and_with(rm2); + rm1.AND(rm2); contains_expected_num_of_registers(rm1, 0); contains_expected_num_of_registers(rm2, 0); } -TEST_VM(RegMask, or_with) { +TEST_VM(RegMask, OR) { RegMask rm1; - rm1.insert(OptoReg::Name(1)); + rm1.Insert(OptoReg::Name(1)); contains_expected_num_of_registers(rm1, 1); - ASSERT_TRUE(rm1.member(OptoReg::Name(1))); + ASSERT_TRUE(rm1.Member(OptoReg::Name(1))); - rm1.or_with(rm1); + rm1.OR(rm1); contains_expected_num_of_registers(rm1, 1); RegMask rm2; - rm1.or_with(rm2); + rm1.OR(rm2); contains_expected_num_of_registers(rm1, 1); contains_expected_num_of_registers(rm2, 0); } -TEST_VM(RegMask, subtract) { +TEST_VM(RegMask, SUBTRACT) { RegMask rm1; RegMask rm2; - rm2.set_all(); + rm2.Set_All(); for (int i = 17; i < (int)rm1.rm_size_in_bits(); i++) { - rm1.insert(i); + rm1.Insert(i); } rm1.set_infinite_stack(true); ASSERT_TRUE(rm1.is_infinite_stack()); - rm2.subtract(rm1); + rm2.SUBTRACT(rm1); contains_expected_num_of_registers(rm1, rm1.rm_size_in_bits() - 17); contains_expected_num_of_registers(rm2, 17); } -TEST_VM(RegMask, subtract_inner) { +TEST_VM(RegMask, SUBTRACT_inner) { RegMask rm1; RegMask rm2; - rm2.set_all(); + rm2.Set_All(); for (int i = 17; i < (int)rm1.rm_size_in_bits(); i++) { - rm1.insert(i); + rm1.Insert(i); } - rm2.subtract_inner(rm1); + rm2.SUBTRACT_inner(rm1); contains_expected_num_of_registers(rm1, rm1.rm_size_in_bits() - 17); contains_expected_num_of_registers(rm2, 17); } @@ -161,11 +161,11 @@ TEST_VM(RegMask, is_bound1) { RegMask rm; ASSERT_FALSE(rm.is_bound1()); for (int i = 0; i < (int)rm.rm_size_in_bits() - 1; i++) { - rm.insert(i); + rm.Insert(i); ASSERT_TRUE(rm.is_bound1()) << "Index " << i; ASSERT_TRUE(rm.is_bound(Op_RegI)) << "Index " << i; contains_expected_num_of_registers(rm, 1); - rm.remove(i); + rm.Remove(i); } // infinite_stack does not count as a bound register rm.set_infinite_stack(true); @@ -176,18 +176,18 @@ TEST_VM(RegMask, is_bound_pair) { RegMask rm; ASSERT_TRUE(rm.is_bound_pair()); for (int i = 0; i < (int)rm.rm_size_in_bits() - 2; i++) { - rm.insert(i); - rm.insert(i + 1); + rm.Insert(i); + rm.Insert(i + 1); ASSERT_TRUE(rm.is_bound_pair()) << "Index " << i; ASSERT_TRUE(rm.is_bound_set(2)) << "Index " << i; ASSERT_TRUE(rm.is_bound(Op_RegI)) << "Index " << i; contains_expected_num_of_registers(rm, 2); - rm.clear(); + rm.Clear(); } // A pair with the infinite bit does not count as a bound pair - rm.clear(); - rm.insert(rm.rm_size_in_bits() - 2); - rm.insert(rm.rm_size_in_bits() - 1); + rm.Clear(); + rm.Insert(rm.rm_size_in_bits() - 2); + rm.Insert(rm.rm_size_in_bits() - 1); rm.set_infinite_stack(true); ASSERT_FALSE(rm.is_bound_pair()); } @@ -198,40 +198,40 @@ TEST_VM(RegMask, is_bound_set) { ASSERT_TRUE(rm.is_bound_set(size)); for (int i = 0; i < (int)rm.rm_size_in_bits() - size; i++) { for (int j = i; j < i + size; j++) { - rm.insert(j); + rm.Insert(j); } ASSERT_TRUE(rm.is_bound_set(size)) << "Size " << size << " Index " << i; contains_expected_num_of_registers(rm, size); - rm.clear(); + rm.Clear(); } // A set with infinite_stack does not count as a bound set for (int j = rm.rm_size_in_bits() - size; j < (int)rm.rm_size_in_bits(); j++) { - rm.insert(j); + rm.Insert(j); } rm.set_infinite_stack(true); ASSERT_FALSE(rm.is_bound_set(size)); - rm.clear(); + rm.Clear(); } } TEST_VM(RegMask, external_member) { RegMask rm; rm.set_infinite_stack(false); - ASSERT_FALSE(rm.member(OptoReg::Name(rm.rm_size_in_bits()))); + ASSERT_FALSE(rm.Member(OptoReg::Name(rm.rm_size_in_bits()))); rm.set_infinite_stack(true); - ASSERT_TRUE(rm.member(OptoReg::Name(rm.rm_size_in_bits()))); + ASSERT_TRUE(rm.Member(OptoReg::Name(rm.rm_size_in_bits()))); } TEST_VM(RegMask, find_element) { RegMask rm; - rm.insert(OptoReg::Name(44)); - rm.insert(OptoReg::Name(30)); - rm.insert(OptoReg::Name(54)); + rm.Insert(OptoReg::Name(44)); + rm.Insert(OptoReg::Name(30)); + rm.Insert(OptoReg::Name(54)); ASSERT_EQ(rm.find_first_elem(), OptoReg::Name(30)); ASSERT_EQ(rm.find_last_elem(), OptoReg::Name(54)); rm.set_infinite_stack(true); ASSERT_EQ(rm.find_last_elem(), OptoReg::Name(54)); - rm.clear(); + rm.Clear(); ASSERT_EQ(rm.find_first_elem(), OptoReg::Bad); ASSERT_EQ(rm.find_last_elem(), OptoReg::Bad); } @@ -242,58 +242,58 @@ TEST_VM(RegMask, find_first_set) { lrg._is_scalable = 0; lrg._is_vector = 0; ASSERT_EQ(rm.find_first_set(lrg, 2), OptoReg::Bad); - rm.insert(OptoReg::Name(24)); - rm.insert(OptoReg::Name(25)); - rm.insert(OptoReg::Name(26)); - rm.insert(OptoReg::Name(27)); - rm.insert(OptoReg::Name(16)); - rm.insert(OptoReg::Name(17)); - rm.insert(OptoReg::Name(18)); - rm.insert(OptoReg::Name(19)); + rm.Insert(OptoReg::Name(24)); + rm.Insert(OptoReg::Name(25)); + rm.Insert(OptoReg::Name(26)); + rm.Insert(OptoReg::Name(27)); + rm.Insert(OptoReg::Name(16)); + rm.Insert(OptoReg::Name(17)); + rm.Insert(OptoReg::Name(18)); + rm.Insert(OptoReg::Name(19)); ASSERT_EQ(rm.find_first_set(lrg, 4), OptoReg::Name(19)); } TEST_VM(RegMask, alignment) { RegMask rm; - rm.insert(OptoReg::Name(30)); - rm.insert(OptoReg::Name(31)); + rm.Insert(OptoReg::Name(30)); + rm.Insert(OptoReg::Name(31)); ASSERT_TRUE(rm.is_aligned_sets(2)); - rm.insert(OptoReg::Name(32)); - rm.insert(OptoReg::Name(37)); - rm.insert(OptoReg::Name(62)); - rm.insert(OptoReg::Name(71)); - rm.insert(OptoReg::Name(74)); - rm.insert(OptoReg::Name(75)); + rm.Insert(OptoReg::Name(32)); + rm.Insert(OptoReg::Name(37)); + rm.Insert(OptoReg::Name(62)); + rm.Insert(OptoReg::Name(71)); + rm.Insert(OptoReg::Name(74)); + rm.Insert(OptoReg::Name(75)); ASSERT_FALSE(rm.is_aligned_pairs()); rm.clear_to_pairs(); ASSERT_TRUE(rm.is_aligned_sets(2)); ASSERT_TRUE(rm.is_aligned_pairs()); contains_expected_num_of_registers(rm, 4); - ASSERT_TRUE(rm.member(OptoReg::Name(30))); - ASSERT_TRUE(rm.member(OptoReg::Name(31))); - ASSERT_TRUE(rm.member(OptoReg::Name(74))); - ASSERT_TRUE(rm.member(OptoReg::Name(75))); + ASSERT_TRUE(rm.Member(OptoReg::Name(30))); + ASSERT_TRUE(rm.Member(OptoReg::Name(31))); + ASSERT_TRUE(rm.Member(OptoReg::Name(74))); + ASSERT_TRUE(rm.Member(OptoReg::Name(75))); ASSERT_FALSE(rm.is_misaligned_pair()); - rm.remove(OptoReg::Name(30)); - rm.remove(OptoReg::Name(74)); + rm.Remove(OptoReg::Name(30)); + rm.Remove(OptoReg::Name(74)); ASSERT_TRUE(rm.is_misaligned_pair()); } TEST_VM(RegMask, clear_to_sets) { RegMask rm; - rm.insert(OptoReg::Name(3)); - rm.insert(OptoReg::Name(20)); - rm.insert(OptoReg::Name(21)); - rm.insert(OptoReg::Name(22)); - rm.insert(OptoReg::Name(23)); - rm.insert(OptoReg::Name(25)); - rm.insert(OptoReg::Name(26)); - rm.insert(OptoReg::Name(27)); - rm.insert(OptoReg::Name(40)); - rm.insert(OptoReg::Name(42)); - rm.insert(OptoReg::Name(43)); - rm.insert(OptoReg::Name(44)); - rm.insert(OptoReg::Name(45)); + rm.Insert(OptoReg::Name(3)); + rm.Insert(OptoReg::Name(20)); + rm.Insert(OptoReg::Name(21)); + rm.Insert(OptoReg::Name(22)); + rm.Insert(OptoReg::Name(23)); + rm.Insert(OptoReg::Name(25)); + rm.Insert(OptoReg::Name(26)); + rm.Insert(OptoReg::Name(27)); + rm.Insert(OptoReg::Name(40)); + rm.Insert(OptoReg::Name(42)); + rm.Insert(OptoReg::Name(43)); + rm.Insert(OptoReg::Name(44)); + rm.Insert(OptoReg::Name(45)); rm.clear_to_sets(2); ASSERT_TRUE(rm.is_aligned_sets(2)); contains_expected_num_of_registers(rm, 10); @@ -307,7 +307,7 @@ TEST_VM(RegMask, clear_to_sets) { TEST_VM(RegMask, smear_to_sets) { RegMask rm; - rm.insert(OptoReg::Name(3)); + rm.Insert(OptoReg::Name(3)); rm.smear_to_sets(2); ASSERT_TRUE(rm.is_aligned_sets(2)); contains_expected_num_of_registers(rm, 2); @@ -327,14 +327,14 @@ TEST_VM(RegMask, overlap) { RegMask rm2; ASSERT_FALSE(rm1.overlap(rm2)); ASSERT_FALSE(rm2.overlap(rm1)); - rm1.insert(OptoReg::Name(23)); - rm1.insert(OptoReg::Name(2)); - rm1.insert(OptoReg::Name(12)); - rm2.insert(OptoReg::Name(1)); - rm2.insert(OptoReg::Name(4)); + rm1.Insert(OptoReg::Name(23)); + rm1.Insert(OptoReg::Name(2)); + rm1.Insert(OptoReg::Name(12)); + rm2.Insert(OptoReg::Name(1)); + rm2.Insert(OptoReg::Name(4)); ASSERT_FALSE(rm1.overlap(rm2)); ASSERT_FALSE(rm2.overlap(rm1)); - rm1.insert(OptoReg::Name(4)); + rm1.Insert(OptoReg::Name(4)); ASSERT_TRUE(rm1.overlap(rm2)); ASSERT_TRUE(rm2.overlap(rm1)); } @@ -342,10 +342,10 @@ TEST_VM(RegMask, overlap) { TEST_VM(RegMask, valid_reg) { RegMask rm; ASSERT_FALSE(rm.is_valid_reg(OptoReg::Name(42), 1)); - rm.insert(OptoReg::Name(3)); - rm.insert(OptoReg::Name(5)); - rm.insert(OptoReg::Name(6)); - rm.insert(OptoReg::Name(7)); + rm.Insert(OptoReg::Name(3)); + rm.Insert(OptoReg::Name(5)); + rm.Insert(OptoReg::Name(6)); + rm.Insert(OptoReg::Name(7)); ASSERT_FALSE(rm.is_valid_reg(OptoReg::Name(7), 4)); ASSERT_TRUE(rm.is_valid_reg(OptoReg::Name(7), 2)); } @@ -355,19 +355,19 @@ TEST_VM(RegMask, rollover_and_insert_remove) { OptoReg::Name reg1(rm.rm_size_in_bits() + 42); OptoReg::Name reg2(rm.rm_size_in_bits() * 2 + 42); rm.set_infinite_stack(true); - ASSERT_TRUE(rm.member(reg1)); + ASSERT_TRUE(rm.Member(reg1)); rm.rollover(); - rm.clear(); - rm.insert(reg1); - ASSERT_TRUE(rm.member(reg1)); - rm.remove(reg1); - ASSERT_FALSE(rm.member(reg1)); + rm.Clear(); + rm.Insert(reg1); + ASSERT_TRUE(rm.Member(reg1)); + rm.Remove(reg1); + ASSERT_FALSE(rm.Member(reg1)); rm.set_infinite_stack(true); rm.rollover(); - rm.clear(); - rm.insert(reg2); - ASSERT_FALSE(rm.member(reg1)); - ASSERT_TRUE(rm.member(reg2)); + rm.Clear(); + rm.Insert(reg2); + ASSERT_FALSE(rm.Member(reg1)); + ASSERT_TRUE(rm.Member(reg2)); } TEST_VM(RegMask, rollover_and_find) { @@ -376,11 +376,11 @@ TEST_VM(RegMask, rollover_and_find) { OptoReg::Name reg2(rm.rm_size_in_bits() + 7); rm.set_infinite_stack(true); rm.rollover(); - rm.clear(); + rm.Clear(); ASSERT_EQ(rm.find_first_elem(), OptoReg::Bad); ASSERT_EQ(rm.find_last_elem(), OptoReg::Bad); - rm.insert(reg1); - rm.insert(reg2); + rm.Insert(reg1); + rm.Insert(reg2); ASSERT_EQ(rm.find_first_elem(), reg2); ASSERT_EQ(rm.find_last_elem(), reg1); } @@ -400,35 +400,35 @@ TEST_VM(RegMask, rollover_and_find_first_set) { OptoReg::Name reg8(rm.rm_size_in_bits() + 19); rm.set_infinite_stack(true); rm.rollover(); - rm.clear(); + rm.Clear(); ASSERT_EQ(rm.find_first_set(lrg, 2), OptoReg::Bad); - rm.insert(reg1); - rm.insert(reg2); - rm.insert(reg3); - rm.insert(reg4); - rm.insert(reg5); - rm.insert(reg6); - rm.insert(reg7); - rm.insert(reg8); + rm.Insert(reg1); + rm.Insert(reg2); + rm.Insert(reg3); + rm.Insert(reg4); + rm.Insert(reg5); + rm.Insert(reg6); + rm.Insert(reg7); + rm.Insert(reg8); ASSERT_EQ(rm.find_first_set(lrg, 4), reg8); } -TEST_VM(RegMask, rollover_and_set_all_from) { +TEST_VM(RegMask, rollover_and_Set_All_From) { RegMask rm; OptoReg::Name reg1(rm.rm_size_in_bits() + 42); rm.set_infinite_stack(true); rm.rollover(); - rm.clear(); - rm.set_all_from(reg1); + rm.Clear(); + rm.Set_All_From(reg1); contains_expected_num_of_registers(rm, rm.rm_size_in_bits() - 42); } -TEST_VM(RegMask, rollover_and_set_all_from_offset) { +TEST_VM(RegMask, rollover_and_Set_All_From_Offset) { RegMask rm; rm.set_infinite_stack(true); rm.rollover(); - rm.clear(); - rm.set_all_from_offset(); + rm.Clear(); + rm.Set_All_From_Offset(); contains_expected_num_of_registers(rm, rm.rm_size_in_bits()); } @@ -440,11 +440,11 @@ TEST_VM(RegMask, rollover_and_iterate) { OptoReg::Name reg4(rm.rm_size_in_bits() + 43); rm.set_infinite_stack(true); rm.rollover(); - rm.clear(); - rm.insert(reg1); - rm.insert(reg2); - rm.insert(reg3); - rm.insert(reg4); + rm.Clear(); + rm.Insert(reg1); + rm.Insert(reg2); + rm.Insert(reg3); + rm.Insert(reg4); RegMaskIterator rmi(rm); ASSERT_EQ(rmi.next(), reg1); ASSERT_EQ(rmi.next(), reg2); @@ -453,45 +453,45 @@ TEST_VM(RegMask, rollover_and_iterate) { ASSERT_FALSE(rmi.has_next()); } -TEST_VM(RegMask, rollover_and_subtract_inner_disjoint) { +TEST_VM(RegMask, rollover_and_SUBTRACT_inner_disjoint) { RegMask rm1; RegMask rm2; OptoReg::Name reg1(rm1.rm_size_in_bits() + 42); rm1.set_infinite_stack(true); rm1.rollover(); - rm1.clear(); - rm1.subtract_inner(rm2); + rm1.Clear(); + rm1.SUBTRACT_inner(rm2); contains_expected_num_of_registers(rm1, 0); - rm2.subtract_inner(rm1); + rm2.SUBTRACT_inner(rm1); contains_expected_num_of_registers(rm2, 0); - rm1.insert(reg1); - rm2.insert(42); - rm1.subtract_inner(rm2); + rm1.Insert(reg1); + rm2.Insert(42); + rm1.SUBTRACT_inner(rm2); contains_expected_num_of_registers(rm1, 1); - rm2.subtract_inner(rm1); + rm2.SUBTRACT_inner(rm1); contains_expected_num_of_registers(rm2, 1); } -TEST_VM(RegMask, rollover_and_subtract_inner_overlap) { +TEST_VM(RegMask, rollover_and_SUBTRACT_inner_overlap) { RegMask rm1; RegMask rm2; OptoReg::Name reg1(rm1.rm_size_in_bits() + 42); rm1.set_infinite_stack(true); rm1.rollover(); - rm1.clear(); + rm1.Clear(); rm2.set_infinite_stack(true); rm2.rollover(); - rm2.clear(); - rm1.subtract_inner(rm2); + rm2.Clear(); + rm1.SUBTRACT_inner(rm2); contains_expected_num_of_registers(rm1, 0); - rm2.subtract_inner(rm1); + rm2.SUBTRACT_inner(rm1); contains_expected_num_of_registers(rm2, 0); - rm1.insert(reg1); - rm2.insert(reg1); - rm1.subtract_inner(rm2); + rm1.Insert(reg1); + rm2.Insert(reg1); + rm1.SUBTRACT_inner(rm2); contains_expected_num_of_registers(rm1, 0); - rm1.insert(reg1); - rm2.subtract_inner(rm1); + rm1.Insert(reg1); + rm2.SUBTRACT_inner(rm1); contains_expected_num_of_registers(rm2, 0); } @@ -502,20 +502,20 @@ TEST_VM_ASSERT_MSG(RegMask, unexpected_clone, ".*clone sanity check") { RegMask rm2; // Copy contents of rm1 to rm2 inappropriately (no copy constructor) memcpy((void*)&rm2, (void*)&rm1, sizeof(RegMask)); - rm2.member(0); // Safeguard in RegMask must catch this. + rm2.Member(0); // Safeguard in RegMask must catch this. } TEST_VM_ASSERT_MSG(RegMask, unexpected_growth, ".*unexpected register mask growth") { RegMask rm; // Add clearly out of range OptoReg::Name - rm.insert(std::numeric_limits::max()); + rm.Insert(std::numeric_limits::max()); } TEST_VM_ASSERT_MSG(RegMask, not_growable, ".*register mask not growable") { RegMask rm; // Add a bit just outside the mask, without having specified an arena for // extension. - rm.insert(rm.rm_size_in_bits()); + rm.Insert(rm.rm_size_in_bits()); } TEST_VM_ASSERT_MSG(RegMask, offset_mismatch, ".*offset mismatch") { @@ -523,8 +523,8 @@ TEST_VM_ASSERT_MSG(RegMask, offset_mismatch, ".*offset mismatch") { RegMask rm2; rm1.set_infinite_stack(true); rm1.rollover(); - // Cannot assign with different offsets - rm2.assignFrom(rm1); + // Cannot copy with different offsets + rm2 = rm1; } #endif @@ -549,8 +549,8 @@ static int first_extended() { static void extend(RegMask& rm, unsigned int n = 4) { // Extend the given RegMask with at least n dynamically-allocated words. - rm.insert(OptoReg::Name(first_extended() + (BitsPerWord * n) - 1)); - rm.clear(); + rm.Insert(OptoReg::Name(first_extended() + (BitsPerWord * n) - 1)); + rm.Clear(); ASSERT_TRUE(rm.rm_size_in_words() >= RegMask::gtest_basic_rm_size_in_words() + n); } @@ -562,14 +562,14 @@ TEST_VM(RegMask, static_by_default) { TEST_VM(RegMask, iteration_extended) { RegMask rm(arena()); - rm.insert(30); - rm.insert(31); - rm.insert(33); - rm.insert(62); - rm.insert(first_extended()); - rm.insert(first_extended() + 42); - rm.insert(first_extended() + 55); - rm.insert(first_extended() + 456); + rm.Insert(30); + rm.Insert(31); + rm.Insert(33); + rm.Insert(62); + rm.Insert(first_extended()); + rm.Insert(first_extended() + 42); + rm.Insert(first_extended() + 55); + rm.Insert(first_extended() + 456); RegMaskIterator rmi(rm); ASSERT_TRUE(rmi.next() == OptoReg::Name(30)); @@ -583,125 +583,125 @@ TEST_VM(RegMask, iteration_extended) { ASSERT_FALSE(rmi.has_next()); } -TEST_VM(RegMask, set_all_extended) { - // Check that set_all doesn't add bits outside of rm.rm_size_bits() on +TEST_VM(RegMask, Set_ALL_extended) { + // Check that Set_All doesn't add bits outside of rm.rm_size_bits() on // extended RegMasks. RegMask rm(arena()); extend(rm); - rm.set_all(); - ASSERT_EQ(rm.size(), rm.rm_size_in_bits()); - ASSERT_TRUE(!rm.is_empty()); - // set_all sets infinite_stack bit + rm.Set_All(); + ASSERT_EQ(rm.Size(), rm.rm_size_in_bits()); + ASSERT_TRUE(!rm.is_Empty()); + // Set_All sets infinite_stack bit ASSERT_TRUE(rm.is_infinite_stack()); contains_expected_num_of_registers(rm, rm.rm_size_in_bits()); } -TEST_VM(RegMask, set_all_from_extended) { +TEST_VM(RegMask, Set_ALL_From_extended) { RegMask rm(arena()); extend(rm); - rm.set_all_from(OptoReg::Name(42)); + rm.Set_All_From(OptoReg::Name(42)); contains_expected_num_of_registers(rm, rm.rm_size_in_bits() - 42); } -TEST_VM(RegMask, set_all_from_extended_grow) { +TEST_VM(RegMask, Set_ALL_From_extended_grow) { RegMask rm(arena()); - rm.set_all_from(first_extended() + OptoReg::Name(42)); + rm.Set_All_From(first_extended() + OptoReg::Name(42)); is_extended(rm); contains_expected_num_of_registers(rm, rm.rm_size_in_bits() - first_extended() - 42); } -TEST_VM(RegMask, clear_extended) { - // Check that clear doesn't leave any stray bits on extended RegMasks. +TEST_VM(RegMask, Clear_extended) { + // Check that Clear doesn't leave any stray bits on extended RegMasks. RegMask rm(arena()); - rm.insert(first_extended()); + rm.Insert(first_extended()); is_extended(rm); - rm.set_all(); - rm.clear(); + rm.Set_All(); + rm.Clear(); contains_expected_num_of_registers(rm, 0); } -TEST_VM(RegMask, and_with_extended_basic) { +TEST_VM(RegMask, AND_extended_basic) { RegMask rm1(arena()); - rm1.insert(OptoReg::Name(first_extended())); + rm1.Insert(OptoReg::Name(first_extended())); is_extended(rm1); contains_expected_num_of_registers(rm1, 1); - ASSERT_TRUE(rm1.member(OptoReg::Name(first_extended()))); + ASSERT_TRUE(rm1.Member(OptoReg::Name(first_extended()))); - rm1.and_with(rm1); + rm1.AND(rm1); contains_expected_num_of_registers(rm1, 1); RegMask rm2; is_basic(rm2); - rm1.and_with(rm2); + rm1.AND(rm2); contains_expected_num_of_registers(rm1, 0); contains_expected_num_of_registers(rm2, 0); } -TEST_VM(RegMask, and_with_extended_extended) { +TEST_VM(RegMask, AND_extended_extended) { RegMask rm1(arena()); - rm1.insert(OptoReg::Name(first_extended())); + rm1.Insert(OptoReg::Name(first_extended())); is_extended(rm1); contains_expected_num_of_registers(rm1, 1); - ASSERT_TRUE(rm1.member(OptoReg::Name(first_extended()))); + ASSERT_TRUE(rm1.Member(OptoReg::Name(first_extended()))); - rm1.and_with(rm1); + rm1.AND(rm1); contains_expected_num_of_registers(rm1, 1); RegMask rm2(arena()); extend(rm2); - rm1.and_with(rm2); + rm1.AND(rm2); contains_expected_num_of_registers(rm1, 0); contains_expected_num_of_registers(rm2, 0); } -TEST_VM(RegMask, or_with_extended_basic) { +TEST_VM(RegMask, OR_extended_basic) { RegMask rm1(arena()); - rm1.insert(OptoReg::Name(first_extended())); + rm1.Insert(OptoReg::Name(first_extended())); is_extended(rm1); contains_expected_num_of_registers(rm1, 1); - ASSERT_TRUE(rm1.member(OptoReg::Name(first_extended()))); + ASSERT_TRUE(rm1.Member(OptoReg::Name(first_extended()))); - rm1.or_with(rm1); + rm1.OR(rm1); contains_expected_num_of_registers(rm1, 1); RegMask rm2; is_basic(rm2); - rm1.or_with(rm2); + rm1.OR(rm2); contains_expected_num_of_registers(rm1, 1); contains_expected_num_of_registers(rm2, 0); } -TEST_VM(RegMask, or_with_extended_extended) { +TEST_VM(RegMask, OR_extended_extended) { RegMask rm1(arena()); - rm1.insert(OptoReg::Name(first_extended())); + rm1.Insert(OptoReg::Name(first_extended())); is_extended(rm1); contains_expected_num_of_registers(rm1, 1); - ASSERT_TRUE(rm1.member(OptoReg::Name(first_extended()))); + ASSERT_TRUE(rm1.Member(OptoReg::Name(first_extended()))); - rm1.or_with(rm1); + rm1.OR(rm1); contains_expected_num_of_registers(rm1, 1); RegMask rm2(arena()); extend(rm2); - rm1.or_with(rm2); + rm1.OR(rm2); contains_expected_num_of_registers(rm1, 1); contains_expected_num_of_registers(rm2, 0); } -TEST_VM(RegMask, subtract_extended) { +TEST_VM(RegMask, SUBTRACT_extended) { RegMask rm1(arena()); extend(rm1); RegMask rm2(arena()); extend(rm2); - rm2.set_all(); + rm2.Set_All(); ASSERT_TRUE(rm2.is_infinite_stack()); for (int i = first_extended() + 17; i < (int)rm1.rm_size_in_bits(); i++) { - rm1.insert(i); + rm1.Insert(i); } rm1.set_infinite_stack(true); ASSERT_TRUE(rm1.is_infinite_stack()); - rm2.subtract(rm1); + rm2.SUBTRACT(rm1); contains_expected_num_of_registers(rm1, rm1.rm_size_in_bits() - first_extended() - 17); contains_expected_num_of_registers(rm2, first_extended() + 17); } @@ -710,9 +710,9 @@ TEST_VM(RegMask, external_member_extended) { RegMask rm(arena()); extend(rm); rm.set_infinite_stack(false); - ASSERT_FALSE(rm.member(OptoReg::Name(rm.rm_size_in_bits()))); + ASSERT_FALSE(rm.Member(OptoReg::Name(rm.rm_size_in_bits()))); rm.set_infinite_stack(true); - ASSERT_TRUE(rm.member(OptoReg::Name(rm.rm_size_in_bits()))); + ASSERT_TRUE(rm.Member(OptoReg::Name(rm.rm_size_in_bits()))); } TEST_VM(RegMask, overlap_extended) { @@ -722,14 +722,14 @@ TEST_VM(RegMask, overlap_extended) { extend(rm2); ASSERT_FALSE(rm1.overlap(rm2)); ASSERT_FALSE(rm2.overlap(rm1)); - rm1.insert(OptoReg::Name(23)); - rm1.insert(OptoReg::Name(2)); - rm1.insert(OptoReg::Name(first_extended() + 12)); - rm2.insert(OptoReg::Name(1)); - rm2.insert(OptoReg::Name(first_extended() + 4)); + rm1.Insert(OptoReg::Name(23)); + rm1.Insert(OptoReg::Name(2)); + rm1.Insert(OptoReg::Name(first_extended() + 12)); + rm2.Insert(OptoReg::Name(1)); + rm2.Insert(OptoReg::Name(first_extended() + 4)); ASSERT_FALSE(rm1.overlap(rm2)); ASSERT_FALSE(rm2.overlap(rm1)); - rm1.insert(OptoReg::Name(first_extended() + 4)); + rm1.Insert(OptoReg::Name(first_extended() + 4)); ASSERT_TRUE(rm1.overlap(rm2)); ASSERT_TRUE(rm2.overlap(rm1)); } @@ -738,43 +738,43 @@ TEST_VM(RegMask, up_extended) { RegMask rm(arena()); extend(rm); ASSERT_TRUE(rm.is_UP()); - rm.insert(OptoReg::Name(1)); + rm.Insert(OptoReg::Name(1)); ASSERT_TRUE(rm.is_UP()); - rm.insert(OptoReg::Name(first_extended())); + rm.Insert(OptoReg::Name(first_extended())); ASSERT_FALSE(rm.is_UP()); - rm.clear(); + rm.Clear(); rm.set_infinite_stack(true); ASSERT_FALSE(rm.is_UP()); } -TEST_VM(RegMask, subtract_inner_basic_extended) { +TEST_VM(RegMask, SUBTRACT_inner_basic_extended) { RegMask rm1; RegMask rm2(arena()); - rm1.insert(OptoReg::Name(1)); - rm1.insert(OptoReg::Name(42)); + rm1.Insert(OptoReg::Name(1)); + rm1.Insert(OptoReg::Name(42)); is_basic(rm1); - rm2.insert(OptoReg::Name(1)); - rm2.insert(OptoReg::Name(first_extended() + 20)); + rm2.Insert(OptoReg::Name(1)); + rm2.Insert(OptoReg::Name(first_extended() + 20)); is_extended(rm2); - rm1.subtract_inner(rm2); + rm1.SUBTRACT_inner(rm2); is_basic(rm1); contains_expected_num_of_registers(rm1, 1); - ASSERT_TRUE(rm1.member(OptoReg::Name(42))); + ASSERT_TRUE(rm1.Member(OptoReg::Name(42))); } -TEST_VM(RegMask, subtract_inner_extended_basic) { +TEST_VM(RegMask, SUBTRACT_inner_extended_basic) { RegMask rm1(arena()); RegMask rm2; - rm1.insert(OptoReg::Name(1)); - rm1.insert(OptoReg::Name(42)); - rm1.insert(OptoReg::Name(first_extended() + 20)); + rm1.Insert(OptoReg::Name(1)); + rm1.Insert(OptoReg::Name(42)); + rm1.Insert(OptoReg::Name(first_extended() + 20)); is_extended(rm1); - rm2.insert(OptoReg::Name(1)); + rm2.Insert(OptoReg::Name(1)); is_basic(rm2); - rm1.subtract_inner(rm2); + rm1.SUBTRACT_inner(rm2); contains_expected_num_of_registers(rm1, 2); - ASSERT_TRUE(rm1.member(OptoReg::Name(42))); - ASSERT_TRUE(rm1.member(OptoReg::Name(first_extended() + 20))); + ASSERT_TRUE(rm1.Member(OptoReg::Name(42))); + ASSERT_TRUE(rm1.Member(OptoReg::Name(first_extended() + 20))); } TEST_VM(RegMask, rollover_extended) { @@ -784,48 +784,48 @@ TEST_VM(RegMask, rollover_extended) { OptoReg::Name reg1(rm.rm_size_in_bits() + 42); rm.set_infinite_stack(true); rm.rollover(); - rm.insert(reg1); - ASSERT_TRUE(rm.member(reg1)); + rm.Insert(reg1); + ASSERT_TRUE(rm.Member(reg1)); } -TEST_VM(RegMask, rollover_and_subtract_inner_disjoint_extended) { +TEST_VM(RegMask, rollover_and_SUBTRACT_inner_disjoint_extended) { RegMask rm1(arena()); RegMask rm2; extend(rm1); OptoReg::Name reg1(rm1.rm_size_in_bits() + 42); rm1.set_infinite_stack(true); rm1.rollover(); - rm1.clear(); - rm1.subtract_inner(rm2); + rm1.Clear(); + rm1.SUBTRACT_inner(rm2); contains_expected_num_of_registers(rm1, 0); - rm2.subtract_inner(rm1); + rm2.SUBTRACT_inner(rm1); contains_expected_num_of_registers(rm2, 0); - rm1.insert(reg1); - rm2.insert(42); - rm1.subtract_inner(rm2); + rm1.Insert(reg1); + rm2.Insert(42); + rm1.SUBTRACT_inner(rm2); contains_expected_num_of_registers(rm1, 1); - rm2.subtract_inner(rm1); + rm2.SUBTRACT_inner(rm1); contains_expected_num_of_registers(rm2, 1); } -TEST_VM(RegMask, rollover_and_subtract_inner_overlap_extended) { +TEST_VM(RegMask, rollover_and_SUBTRACT_inner_overlap_extended) { RegMask rm1(arena()); RegMask rm2; OptoReg::Name reg1(rm1.rm_size_in_bits() + 42); extend(rm1); rm2.set_infinite_stack(true); rm2.rollover(); - rm2.clear(); - rm1.subtract_inner(rm2); + rm2.Clear(); + rm1.SUBTRACT_inner(rm2); contains_expected_num_of_registers(rm1, 0); - rm2.subtract_inner(rm1); + rm2.SUBTRACT_inner(rm1); contains_expected_num_of_registers(rm2, 0); - rm1.insert(reg1); - rm2.insert(reg1); - rm1.subtract_inner(rm2); + rm1.Insert(reg1); + rm2.Insert(reg1); + rm1.SUBTRACT_inner(rm2); contains_expected_num_of_registers(rm1, 0); - rm1.insert(reg1); - rm2.subtract_inner(rm1); + rm1.Insert(reg1); + rm2.SUBTRACT_inner(rm1); contains_expected_num_of_registers(rm2, 0); } @@ -855,7 +855,7 @@ static void print(const char* name, const RegMask& mask) { static void assert_equivalent(const RegMask& mask, const ResourceBitMap& mask_ref, bool infinite_stack_ref) { - ASSERT_EQ(mask_ref.count_one_bits(), mask.size()); + ASSERT_EQ(mask_ref.count_one_bits(), mask.Size()); RegMaskIterator it(mask); OptoReg::Name reg = OptoReg::Bad; while (it.has_next()) { @@ -870,7 +870,7 @@ static void populate_auxiliary_sets(RegMask& mask_aux, ResourceBitMap& mask_aux_ref, uint reg_capacity, uint offset, bool random_offset) { - mask_aux.clear(); + mask_aux.Clear(); mask_aux_ref.clear(); if (random_offset) { uint offset_in_words = offset / BitsPerWord; @@ -936,7 +936,7 @@ static void populate_auxiliary_sets(RegMask& mask_aux, } for (uint i = 0; i < regs; i++) { uint reg = (next_random() % max_size) + offset; - mask_aux.insert(reg); + mask_aux.Insert(reg); mask_aux_ref.set_bit(reg); } mask_aux.set_infinite_stack(next_random() % 2); @@ -994,7 +994,7 @@ TEST_VM(RegMask, random) { OptoReg::dump(reg); tty->cr(); } - mask.insert(reg); + mask.Insert(reg); mask_ref.set_bit(reg); if (mask.is_infinite_stack() && reg >= size_bits_before) { // Stack-extend reference bitset. @@ -1010,36 +1010,36 @@ TEST_VM(RegMask, random) { OptoReg::dump(reg); tty->cr(); } - mask.remove(reg); + mask.Remove(reg); mask_ref.clear_bit(reg); break; case 2: if (Verbose) { tty->print_cr("action: Clear"); } - mask.clear(); + mask.Clear(); mask_ref.clear(); infinite_stack_ref = false; break; case 3: if (offset_ref > 0) { - // set_all expects a zero-offset. + // Set_All expects a zero-offset. break; } if (Verbose) { - tty->print_cr("action: set_all"); + tty->print_cr("action: Set_All"); } - mask.set_all(); + mask.Set_All(); mask_ref.set_range(0, size_bits_before); infinite_stack_ref = true; break; case 4: if (Verbose) { - tty->print_cr("action: and_with"); + tty->print_cr("action: AND"); } populate_auxiliary_sets(mask_aux, mask_aux_ref, mask.rm_size_in_bits(), offset_ref, /*random_offset*/ false); - mask.and_with(mask_aux); + mask.AND(mask_aux); stack_extend_ref_masks(mask_ref, infinite_stack_ref, size_bits_before, offset_ref, mask_aux_ref, mask_aux.is_infinite_stack(), mask_aux.rm_size_in_bits(), mask_aux.offset_bits()); @@ -1048,11 +1048,11 @@ TEST_VM(RegMask, random) { break; case 5: if (Verbose) { - tty->print_cr("action: or_with"); + tty->print_cr("action: OR"); } populate_auxiliary_sets(mask_aux, mask_aux_ref, mask.rm_size_in_bits(), offset_ref, /*random_offset*/ false); - mask.or_with(mask_aux); + mask.OR(mask_aux); stack_extend_ref_masks(mask_ref, infinite_stack_ref, size_bits_before, offset_ref, mask_aux_ref, mask_aux.is_infinite_stack(), mask_aux.rm_size_in_bits(), mask_aux.offset_bits()); @@ -1061,11 +1061,11 @@ TEST_VM(RegMask, random) { break; case 6: if (Verbose) { - tty->print_cr("action: subtract"); + tty->print_cr("action: SUBTRACT"); } populate_auxiliary_sets(mask_aux, mask_aux_ref, mask.rm_size_in_bits(), offset_ref, /*random_offset*/ false); - mask.subtract(mask_aux); + mask.SUBTRACT(mask_aux); stack_extend_ref_masks(mask_ref, infinite_stack_ref, size_bits_before, offset_ref, mask_aux_ref, mask_aux.is_infinite_stack(), mask_aux.rm_size_in_bits(), mask_aux.offset_bits()); @@ -1076,15 +1076,15 @@ TEST_VM(RegMask, random) { break; case 7: if (Verbose) { - tty->print_cr("action: subtract_inner"); + tty->print_cr("action: SUBTRACT_inner"); } populate_auxiliary_sets(mask_aux, mask_aux_ref, mask.rm_size_in_bits(), offset_ref, /*random_offset*/ true); - // subtract_inner expects an argument register mask with infinite_stack = + // SUBTRACT_inner expects an argument register mask with infinite_stack = // false. mask_aux.set_infinite_stack(false); - mask.subtract_inner(mask_aux); - // subtract_inner does not have "stack-extension semantics". + mask.SUBTRACT_inner(mask_aux); + // SUBTRACT_inner does not have "stack-extension semantics". mask_ref.set_difference(mask_aux_ref); break; case 8: @@ -1106,7 +1106,7 @@ TEST_VM(RegMask, random) { tty->print_cr("action: rollover"); } // rollover expects the mask to be cleared and with infinite_stack = true - mask.clear(); + mask.Clear(); mask.set_infinite_stack(true); mask_ref.clear(); infinite_stack_ref = true; @@ -1120,28 +1120,28 @@ TEST_VM(RegMask, random) { tty->print_cr("action: reset"); } mask.gtest_set_offset(0); - mask.clear(); + mask.Clear(); mask_ref.clear(); infinite_stack_ref = false; offset_ref = 0; break; case 11: if (Verbose) { - tty->print_cr("action: set_all_from_offset"); + tty->print_cr("action: Set_All_From_Offset"); } - mask.set_all_from_offset(); + mask.Set_All_From_Offset(); mask_ref.set_range(offset_ref, offset_ref + size_bits_before); infinite_stack_ref = true; break; case 12: reg = (next_random() % size_bits_before) + offset_ref; if (Verbose) { - tty->print_cr("action: set_all_from"); + tty->print_cr("action: Set_All_From"); tty->print("value : "); OptoReg::dump(reg); tty->cr(); } - mask.set_all_from(reg); + mask.Set_All_From(reg); mask_ref.set_range(reg, offset_ref + size_bits_before); infinite_stack_ref = true; break; @@ -1154,12 +1154,12 @@ TEST_VM(RegMask, random) { // Randomly sets register mask contents. Does not change register mask size. static void randomize(RegMask& rm) { - rm.clear(); + rm.Clear(); // Uniform distribution over number of registers. uint regs = next_random() % (rm.rm_size_in_bits() + 1); for (uint i = 0; i < regs; i++) { uint reg = (next_random() % rm.rm_size_in_bits()) + rm.offset_bits(); - rm.insert(reg); + rm.Insert(reg); } rm.set_infinite_stack(next_random() % 2); } @@ -1175,10 +1175,10 @@ static uint grow_randomly(RegMask& rm, uint min_growth = 1, break; } // Force grow - rm.insert(reg); + rm.Insert(reg); if (!rm.is_infinite_stack()) { // Restore - rm.remove(reg); + rm.Remove(reg); } } // Return how many times we grew @@ -1241,8 +1241,8 @@ TEST_VM(RegMask, random_copy) { // Randomly initialize source randomize(src); - // Set destination to source - dst.assignFrom(src); + // Copy source to destination + dst = src; // Check equality bool passed = src.gtest_equals(dst); diff --git a/test/hotspot/jtreg/ProblemList-Virtual.txt b/test/hotspot/jtreg/ProblemList-Virtual.txt index 3168466219493..3c74d7bf81658 100644 --- a/test/hotspot/jtreg/ProblemList-Virtual.txt +++ b/test/hotspot/jtreg/ProblemList-Virtual.txt @@ -33,6 +33,11 @@ vmTestbase/vm/mlvm/indy/func/jvmti/mergeCP_indy2manyDiff_a/TestDescription.java vmTestbase/nsk/jvmti/CompiledMethodUnload/compmethunload001/TestDescription.java 8300711 generic-all +#### +## Tests for functionality which currently is not supported for virtual threads + +vmTestbase/nsk/jvmti/GetCurrentThreadCpuTime/curthrcputime001/TestDescription.java 8348844 generic-all +vmTestbase/nsk/jvmti/GetThreadCpuTime/thrcputime001/TestDescription.java 8348844 generic-all #### ## Test fails because it expects to find vthreads in GetAllThreads @@ -77,3 +82,14 @@ vmTestbase/nsk/jdi/VMOutOfMemoryException/VMOutOfMemoryException001/VMOutOfMemor # to make progress when all other threads are currently suspended. vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended002/TestDescription.java 8338713 generic-all +########## +## Tests incompatible with with virtual test thread factory. +## There is no goal to run all test with virtual test thread factory. +## So any test migth be added as incompatible, the bug is not required. + +gc/arguments/TestNewSizeThreadIncrease.java 0000000 generic-all +gc/g1/TestSkipRebuildRemsetPhase.java 0000000 generic-all +runtime/ErrorHandling/MachCodeFramesInErrorFile.java 0000000 generic-all +runtime/Thread/AsyncExceptionOnMonitorEnter.java 0000000 generic-all +runtime/Thread/StopAtExit.java 0000000 generic-all +runtime/handshake/HandshakeWalkStackTest.java 0000000 generic-all diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index b1c03553dfc4f..f02ba70ba874e 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -133,7 +133,7 @@ containers/docker/TestJcmdWithSideCar.java 8341518 linux-x64 # :hotspot_serviceability # 8239062 and 8270326 only affects macosx-x64,macosx-aarch64 -serviceability/sa/sadebugd/DebugdConnectTest.java 8239062,8270326 generic-all +serviceability/sa/sadebugd/DebugdConnectTest.java 8239062,8270326,8344261 generic-all serviceability/sa/TestRevPtrsForInvokeDynamic.java 8241235 generic-all serviceability/jvmti/vthread/GetThreadStateMountedTest/GetThreadStateMountedTest.java 8318090,8318729 generic-all @@ -153,6 +153,10 @@ serviceability/sa/ClhsdbThreadContext.java 8356704 windows-x64 serviceability/jvmti/stress/StackTrace/NotSuspended/GetStackTraceNotSuspendedStressTest.java 8315980 linux-all,windows-x64 +serviceability/sa/JhsdbThreadInfoTest.java 8344261 generic-all +serviceability/sa/TestJhsdbJstackLock.java 8344261 generic-all +serviceability/attach/RemovingUnixDomainSocketTest.java 8344261 generic-all + ############################################################################# # :hotspot_misc diff --git a/test/hotspot/jtreg/TEST.groups b/test/hotspot/jtreg/TEST.groups index 18f27a9662818..fd9dd6eb4c021 100644 --- a/test/hotspot/jtreg/TEST.groups +++ b/test/hotspot/jtreg/TEST.groups @@ -570,7 +570,6 @@ hotspot_aot_classlinking = \ -runtime/cds/appcds/TestSerialGCWithCDS.java \ -runtime/cds/appcds/TestZGCWithCDS.java \ -runtime/cds/appcds/TestWithProfiler.java \ - -runtime/cds/appcds/VerifyObjArrayCloneTest.java \ -runtime/cds/serviceability/ReplaceCriticalClassesForSubgraphs.java \ -runtime/cds/serviceability/ReplaceCriticalClasses.java \ -runtime/cds/serviceability/transformRelatedClasses/TransformInterfaceAndImplementor.java \ diff --git a/test/hotspot/jtreg/compiler/c2/TestBit.java b/test/hotspot/jtreg/compiler/c2/TestBit.java index 01769470d78c0..b1186a85cae15 100644 --- a/test/hotspot/jtreg/compiler/c2/TestBit.java +++ b/test/hotspot/jtreg/compiler/c2/TestBit.java @@ -33,7 +33,7 @@ * @library /test/lib / * * @requires vm.flagless - * @requires os.arch == "aarch64" | os.arch == "amd64" | os.arch == "x86_64" | os.arch == "ppc64" | os.arch == "ppc64le" | os.arch == "riscv64" + * @requires os.arch=="aarch64" | os.arch=="amd64" | os.arch == "ppc64" | os.arch == "ppc64le" | os.arch == "riscv64" * @requires vm.debug == true & vm.compiler2.enabled * * @run driver compiler.c2.TestBit diff --git a/test/hotspot/jtreg/compiler/c2/irTests/LShiftINodeIdealizationTests.java b/test/hotspot/jtreg/compiler/c2/irTests/LShiftINodeIdealizationTests.java index 7db56e2a87852..0b2a87fb2c536 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/LShiftINodeIdealizationTests.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/LShiftINodeIdealizationTests.java @@ -54,17 +54,6 @@ public static void main(String[] args) { "testDoubleShift9", "testDoubleShiftSliceAndStore", "testRandom", - "testShiftValue", - "testShiftValueOverflow", - "testShiftMultiple32", - "testShiftOfAddSameInput", - "testLargeShiftOfAddSameInput", - "testShiftOfAddConstant", - "testLShiftOfAndOfRShiftSameCon", - "testLShiftOfAndOfURShiftSameCon", - "testLShiftOfAndOfRShift", - "testLShiftOfAndOfURShift", - "testLShiftOfAndOfCon", }) public void runMethod() { int a = RunInfo.getRandom().nextInt(); @@ -82,29 +71,6 @@ public void runMethod() { assertResult(d); assertResult(min); assertResult(max); - - Asserts.assertEQ(42 << 1, testShiftValue(42)); - Asserts.assertEQ(Integer.MAX_VALUE << 1, testShiftValueOverflow(Integer.MAX_VALUE)); - Asserts.assertEQ((Integer.MAX_VALUE-1) << 1, testShiftValueOverflow(Integer.MAX_VALUE-1)); - - assertResult(a, b); - assertResult(c, d); - assertResult(a, min); - assertResult(a, max); - assertResult(min, a); - assertResult(max, a); - assertResult(min, max); - assertResult(max, min); - assertResult(min, min); - assertResult(max, max); - } - - private void assertResult(int a, int b) { - otherInput = b; - Asserts.assertEQ(((a >> 4) & b) << 4, testLShiftOfAndOfRShiftSameCon(a)); - Asserts.assertEQ(((a >>> 4) & b) << 4, testLShiftOfAndOfURShiftSameCon(a)); - Asserts.assertEQ(((a >> 4) & b) << 8, testLShiftOfAndOfRShift(a)); - Asserts.assertEQ(((a >>> 4) & b) << 8, testLShiftOfAndOfURShift(a)); } @DontCompile @@ -117,11 +83,6 @@ public void assertResult(int a) { Asserts.assertEQ((a >>> 8) << 4, test6(a)); Asserts.assertEQ(((a >> 4) & 0xFF) << 8, test7(a)); Asserts.assertEQ(((a >>> 4) & 0xFF) << 8, test8(a)); - Asserts.assertEQ(a, testShiftMultiple32(a)); - Asserts.assertEQ((a + a) << 1, testShiftOfAddSameInput(a)); - Asserts.assertEQ((a + a) << 31, testLargeShiftOfAddSameInput(a)); - Asserts.assertEQ(((a + 1) << 1) + 1, testShiftOfAddConstant(a)); - Asserts.assertEQ((a & ((1 << (32 - 10)) -1)) << 10, testLShiftOfAndOfCon(a)); assertDoubleShiftResult(a); } @@ -306,107 +267,4 @@ public short[] testDoubleShiftSliceAndStore(short[] a) { public int testRandom(int x) { return (x << CON0) << CON1; } - - @Test - @IR(counts = {IRNode.LSHIFT, "1"}, failOn = { IRNode.IF } ) - public int testShiftValue(int x) { - x = Integer.min(Integer.max(x, 10), 100); - int shift = x << 1; - if (shift > 200 || shift < 20) { - throw new RuntimeException("never taken"); - } - return shift; - } - - @Test - @IR(counts = {IRNode.LSHIFT, "1", IRNode.IF, "2" } ) - public int testShiftValueOverflow(int x) { - x = Integer.max(x, Integer.MAX_VALUE - 1); - int shift = x << 1; - if (shift != -2 && shift != -4) { - throw new RuntimeException("never taken"); - } - return shift; - } - - @Test - @IR(failOn = { IRNode.LSHIFT_I } ) - public int testShiftMultiple32(int x) { - return x << 128; - } - - @Test - @IR(counts = { IRNode.LSHIFT_I, "1" }, failOn = { IRNode.ADD_I } ) - public int testShiftOfAddSameInput(int x) { - return (x + x) << 1; - } - - @Test - @IR(counts = { IRNode.LSHIFT_I, "1", IRNode.ADD_I, "1" } ) - public int testLargeShiftOfAddSameInput(int x) { - return (x + x) << 31; - } - - @Test - @IR(counts = { IRNode.LSHIFT_I, "1", IRNode.ADD_I, "1" } ) - public int testShiftOfAddConstant(int x) { - return ((x + 1) << 1) + 1; - } - - static short shortField; - static byte byteField; - - @Test - @IR(counts = { IRNode.ADD_I, "1"} , failOn = { IRNode.LSHIFT_I, IRNode.RSHIFT_I } ) - @Arguments( values = { Argument.NUMBER_42 }) - public void testStoreShort(int x) { - shortField = (short)(x + x); - } - - @Test - @IR(counts = { IRNode.ADD_I, "1"} , failOn = { IRNode.LSHIFT_I, IRNode.RSHIFT_I } ) - @Arguments( values = { Argument.NUMBER_42 }) - public void testStoreByte(int x) { - byteField = (byte)(x + x); - } - - static int otherInput; - - @Test - @IR(counts = { IRNode.AND_I, "1", IRNode.LSHIFT_I, "1" } , failOn = { IRNode.RSHIFT_I } ) - public int testLShiftOfAndOfRShiftSameCon(int x) { - int shift = x >> 4; - int y = otherInput; - return (shift & y) << 4; - } - - @Test - @IR(counts = { IRNode.AND_I, "1", IRNode.LSHIFT_I, "1" } , failOn = { IRNode.URSHIFT_I } ) - public int testLShiftOfAndOfURShiftSameCon(int x) { - int shift = x >>> 4; - int y = otherInput; - return (shift & y) << 4; - } - - @Test - @IR(counts = { IRNode.AND_I, "2", IRNode.LSHIFT_I, "2" } , failOn = { IRNode.RSHIFT_I } ) - public int testLShiftOfAndOfRShift(int x) { - int shift = x >> 4; - int y = otherInput; - return (shift & y) << 8; - } - - @Test - @IR(counts = { IRNode.AND_I, "2", IRNode.LSHIFT_I, "2" } , failOn = { IRNode.URSHIFT_I } ) - public int testLShiftOfAndOfURShift(int x) { - int shift = x >>> 4; - int y = otherInput; - return (shift & y) << 8; - } - - @Test - @IR(counts = { IRNode.LSHIFT_I, "1" } , failOn = { IRNode.AND_I } ) - public int testLShiftOfAndOfCon(int x) { - return (x & ((1 << (32 - 10)) -1)) << 10; - } } diff --git a/test/hotspot/jtreg/compiler/c2/irTests/LShiftLNodeIdealizationTests.java b/test/hotspot/jtreg/compiler/c2/irTests/LShiftLNodeIdealizationTests.java index f489a348eefa5..11eb928d564a6 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/LShiftLNodeIdealizationTests.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/LShiftLNodeIdealizationTests.java @@ -52,17 +52,6 @@ public static void main(String[] args) { "testDoubleShift8", "testDoubleShift9", "testRandom", - "testShiftValue", - "testShiftValueOverflow", - "testShiftMultiple64", - "testShiftOfAddSameInput", - "testLargeShiftOfAddSameInput", - "testShiftOfAddConstant", - "testLShiftOfAndOfRShiftSameCon", - "testLShiftOfAndOfURShiftSameCon", - "testLShiftOfAndOfRShift", - "testLShiftOfAndOfURShift", - "testLShiftOfAndOfCon", }) public void runMethod() { long a = RunInfo.getRandom().nextLong(); @@ -80,29 +69,6 @@ public void runMethod() { assertResult(d); assertResult(min); assertResult(max); - - Asserts.assertEQ(42L << 1, testShiftValue(42)); - Asserts.assertEQ(Long.MAX_VALUE << 1, testShiftValueOverflow(Long.MAX_VALUE)); - Asserts.assertEQ((Long.MAX_VALUE-1) << 1, testShiftValueOverflow(Long.MAX_VALUE-1)); - - assertResult(a, b); - assertResult(c, d); - assertResult(a, min); - assertResult(a, max); - assertResult(min, a); - assertResult(max, a); - assertResult(min, max); - assertResult(max, min); - assertResult(min, min); - assertResult(max, max); - } - - private void assertResult(long a, long b) { - otherInput = b; - Asserts.assertEQ(((a >> 4) & b) << 4, testLShiftOfAndOfRShiftSameCon(a)); - Asserts.assertEQ(((a >>> 4) & b) << 4, testLShiftOfAndOfURShiftSameCon(a)); - Asserts.assertEQ(((a >> 4) & b) << 8, testLShiftOfAndOfRShift(a)); - Asserts.assertEQ(((a >>> 4) & b) << 8, testLShiftOfAndOfURShift(a)); } @DontCompile @@ -113,11 +79,6 @@ public void assertResult(long a) { Asserts.assertEQ((a >>> 8L) << 4L, test6(a)); Asserts.assertEQ(((a >> 4L) & 0xFFL) << 8L, test7(a)); Asserts.assertEQ(((a >>> 4L) & 0xFFL) << 8L, test8(a)); - Asserts.assertEQ(a, testShiftMultiple64(a)); - Asserts.assertEQ((a + a) << 1, testShiftOfAddSameInput(a)); - Asserts.assertEQ((a + a) << 63, testLargeShiftOfAddSameInput(a)); - Asserts.assertEQ(((a + 1) << 1) + 1, testShiftOfAddConstant(a)); - Asserts.assertEQ((a & ((1L << (64 - 10)) -1)) << 10, testLShiftOfAndOfCon(a)); assertDoubleShiftResult(a); } @@ -272,90 +233,4 @@ public long testDoubleShift9(long x) { public long testRandom(long x) { return (x << CON0) << CON1; } - - @Test - @IR(counts = {IRNode.LSHIFT, "1"}, failOn = { IRNode.IF } ) - public long testShiftValue(long x) { - x = Long.min(Long.max(x, 10), 100); - long shift = x << 1; - if (shift > 200 || shift < 20) { - throw new RuntimeException("never taken"); - } - return shift; - } - - @Test - @IR(counts = {IRNode.LSHIFT, "1", IRNode.IF, "2" } ) - public long testShiftValueOverflow(long x) { - x = Long.max(x, Long.MAX_VALUE - 1); - long shift = x << 1; - if (shift != -2 && shift != -4) { - throw new RuntimeException("never taken"); - } - return shift; - } - - @Test - @IR(failOn = { IRNode.LSHIFT_L } ) - public long testShiftMultiple64(long x) { - return x << 128; - } - - @Test - @IR(counts = { IRNode.LSHIFT_L, "1" }, failOn = { IRNode.ADD_L } ) - public long testShiftOfAddSameInput(long x) { - return (x + x) << 1; - } - - @Test - @IR(counts = { IRNode.LSHIFT_L, "1", IRNode.ADD_L, "1" } ) - public long testLargeShiftOfAddSameInput(long x) { - return (x + x) << 63; - } - - @Test - @IR(counts = { IRNode.LSHIFT_L, "1", IRNode.ADD_L, "1" } ) - public long testShiftOfAddConstant(long x) { - return ((x + 1) << 1) + 1; - } - - static long otherInput; - - @Test - @IR(counts = { IRNode.AND_L, "1", IRNode.LSHIFT_L, "1" } , failOn = { IRNode.RSHIFT_L } ) - public long testLShiftOfAndOfRShiftSameCon(long x) { - long shift = x >> 4; - long y = otherInput; - return (shift & y) << 4; - } - - @Test - @IR(counts = { IRNode.AND_L, "1", IRNode.LSHIFT_L, "1" } , failOn = { IRNode.URSHIFT_L } ) - public long testLShiftOfAndOfURShiftSameCon(long x) { - long shift = x >>> 4; - long y = otherInput; - return (shift & y) << 4; - } - - @Test - @IR(counts = { IRNode.AND_L, "2", IRNode.LSHIFT_L, "2" } , failOn = { IRNode.RSHIFT_L } ) - public long testLShiftOfAndOfRShift(long x) { - long shift = x >> 4; - long y = otherInput; - return (shift & y) << 8; - } - - @Test - @IR(counts = { IRNode.AND_L, "2", IRNode.LSHIFT_L, "2" } , failOn = { IRNode.URSHIFT_L } ) - public long testLShiftOfAndOfURShift(long x) { - long shift = x >>> 4; - long y = otherInput; - return (shift & y) << 8; - } - - @Test - @IR(counts = { IRNode.LSHIFT_L, "1" } , failOn = { IRNode.AND_L } ) - public long testLShiftOfAndOfCon(long x) { - return (x & ((1L << (64 - 10)) -1)) << 10; - } } diff --git a/test/hotspot/jtreg/compiler/c2/irTests/RotateLeftNodeIntIdealizationTests.java b/test/hotspot/jtreg/compiler/c2/irTests/RotateLeftNodeIntIdealizationTests.java index f5225e8173c3e..e3651129daaf3 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/RotateLeftNodeIntIdealizationTests.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/RotateLeftNodeIntIdealizationTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,7 @@ * @summary Test that Ideal transformations of RotateLeftNode* are being performed as expected. * @library /test/lib / * @run driver compiler.c2.irTests.RotateLeftNodeIntIdealizationTests - * @requires os.arch == "amd64" | os.arch == "x86_64" | os.arch == "aarch64" | (os.arch == "riscv64" & vm.cpu.features ~= ".*zbb.*") + * @requires os.arch == "x86_64" | os.arch == "aarch64" | (os.arch == "riscv64" & vm.cpu.features ~= ".*zbb.*") */ public class RotateLeftNodeIntIdealizationTests { diff --git a/test/hotspot/jtreg/compiler/c2/irTests/RotateLeftNodeLongIdealizationTests.java b/test/hotspot/jtreg/compiler/c2/irTests/RotateLeftNodeLongIdealizationTests.java index b28d2f6dc8be5..190f08d348ced 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/RotateLeftNodeLongIdealizationTests.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/RotateLeftNodeLongIdealizationTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,7 @@ * @summary Test that Ideal transformations of RotateLeftNode* are being performed as expected. * @library /test/lib / * @run driver compiler.c2.irTests.RotateLeftNodeLongIdealizationTests - * @requires os.arch == "amd64" | os.arch == "x86_64" | os.arch == "aarch64" | (os.arch == "riscv64" & vm.cpu.features ~= ".*zbb.*") + * @requires os.arch == "x86_64" | os.arch == "aarch64" | (os.arch == "riscv64" & vm.cpu.features ~= ".*zbb.*") */ public class RotateLeftNodeLongIdealizationTests { diff --git a/test/hotspot/jtreg/compiler/calls/common/InvokeDynamicPatcher.java b/test/hotspot/jtreg/compiler/calls/common/InvokeDynamicPatcher.java index d5c93ebaf5e4c..b82e06317d2d7 100644 --- a/test/hotspot/jtreg/compiler/calls/common/InvokeDynamicPatcher.java +++ b/test/hotspot/jtreg/compiler/calls/common/InvokeDynamicPatcher.java @@ -23,121 +23,150 @@ package compiler.calls.common; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Handle; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + +import java.io.FileInputStream; import java.io.IOException; -import java.lang.classfile.ClassFile; -import java.lang.classfile.ClassTransform; -import java.lang.classfile.CodeBuilder; -import java.lang.classfile.CodeElement; -import java.lang.classfile.CodeTransform; -import java.lang.classfile.Label; -import java.lang.constant.ClassDesc; -import java.lang.constant.DirectMethodHandleDesc; -import java.lang.constant.DynamicCallSiteDesc; -import java.lang.constant.MethodHandleDesc; -import java.lang.constant.MethodTypeDesc; import java.lang.invoke.CallSite; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.net.URISyntaxException; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; import java.nio.file.StandardOpenOption; -import static java.lang.constant.ConstantDescs.*; - /** * A class which patch InvokeDynamic class bytecode with invokydynamic instruction, rewriting "caller" method to call "callee" method using invokedynamic */ -public final class InvokeDynamicPatcher { +public class InvokeDynamicPatcher extends ClassVisitor { - private static final ClassDesc CLASS = InvokeDynamic.class.describeConstable().orElseThrow(); + private static final String CLASS = InvokeDynamic.class.getName() + .replace('.', '/'); private static final String CALLER_METHOD_NAME = "caller"; private static final String CALLEE_METHOD_NAME = "callee"; private static final String NATIVE_CALLEE_METHOD_NAME = "calleeNative"; private static final String BOOTSTRAP_METHOD_NAME = "bootstrapMethod"; private static final String CALL_NATIVE_FIELD = "nativeCallee"; - private static final ClassDesc CALL_NATIVE_FIELD_DESC = CD_boolean; - private static final MethodTypeDesc CALLEE_METHOD_DESC = MethodTypeDesc.of( - CD_boolean, CLASS, CD_int, CD_long, CD_float, CD_double, CD_String); - private static final MethodTypeDesc ASSERTTRUE_METHOD_DESC = MethodTypeDesc.of( - CD_void, CD_boolean, CD_String); - private static final ClassDesc ASSERTS_CLASS = ClassDesc.ofInternalName("jdk/test/lib/Asserts"); + private static final String CALL_NATIVE_FIELD_DESC = "Z"; + private static final String CALLEE_METHOD_DESC + = "(L" + CLASS + ";IJFDLjava/lang/String;)Z"; + private static final String ASSERTTRUE_METHOD_DESC + = "(ZLjava/lang/String;)V"; + private static final String ASSERTS_CLASS = "jdk/test/lib/Asserts"; private static final String ASSERTTRUE_METHOD_NAME = "assertTrue"; - public static void main(String args[]) throws IOException, URISyntaxException { - Path filePath = Path.of(InvokeDynamic.class.getProtectionDomain().getCodeSource() - .getLocation().toURI()).resolve(InvokeDynamic.class.getName().replace('.', '/') +".class"); - var bytes = ClassFile.of().transformClass(ClassFile.of().parse(filePath), - ClassTransform.transformingMethodBodies(m -> m.methodName().equalsString(CALLER_METHOD_NAME), new CodeTransform() { - @Override - public void accept(CodeBuilder builder, CodeElement element) { - // discard - } + public static void main(String args[]) { + ClassReader cr; + Path filePath; + try { + filePath = Paths.get(InvokeDynamic.class.getProtectionDomain().getCodeSource() + .getLocation().toURI()).resolve(CLASS + ".class"); + } catch (URISyntaxException ex) { + throw new Error("TESTBUG: Can't get code source" + ex, ex); + } + try (FileInputStream fis = new FileInputStream(filePath.toFile())) { + cr = new ClassReader(fis); + } catch (IOException e) { + throw new Error("Error reading file", e); + } + ClassWriter cw = new ClassWriter(cr, + ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); + cr.accept(new InvokeDynamicPatcher(Opcodes.ASM5, cw), 0); + try { + Files.write(filePath, cw.toByteArray(), + StandardOpenOption.WRITE); + } catch (IOException e) { + throw new Error(e); + } + } + + public InvokeDynamicPatcher(int api, ClassWriter cw) { + super(api, cw); + } - /* the code generated looks like - * 0: aload_0 - * 1: ldc #125 // int 1 - * 3: ldc2_w #126 // long 2l - * 6: ldc #128 // float 3.0f - * 8: ldc2_w #129 // double 4.0d - * 11: ldc #132 // String 5 - * 13: aload_0 - * 14: getfield #135 // Field nativeCallee:Z - * 17: ifeq 28 - * 20: invokedynamic #181, 0 // InvokeDynamic #1:calleeNative:(Lcompiler/calls/common/InvokeDynamic;IJFDLjava/lang/String;)Z - * 25: goto 33 - * 28: invokedynamic #183, 0 // InvokeDynamic #1:callee:(Lcompiler/calls/common/InvokeDynamic;IJFDLjava/lang/String;)Z - * 33: ldc #185 // String Call insuccessfull - * 35: invokestatic #191 // Method jdk/test/lib/Asserts.assertTrue:(ZLjava/lang/String;)V - * 38: return - * - * or, using java-like pseudo-code - * if (this.nativeCallee == false) { - * invokedynamic-call-return-value = invokedynamic-of-callee - * } else { - * invokedynamic-call-return-value = invokedynamic-of-nativeCallee - * } - * Asserts.assertTrue(invokedynamic-call-return-value, error-message); - * return; - */ - @Override - public void atEnd(CodeBuilder builder) { - Label nonNativeLabel = builder.newLabel(); - Label checkLabel = builder.newLabel(); - MethodType mtype = MethodType.methodType(CallSite.class, - MethodHandles.Lookup.class, String.class, MethodType.class); - DirectMethodHandleDesc dmh = MethodHandleDesc.of(DirectMethodHandleDesc.Kind.STATIC, - CLASS, BOOTSTRAP_METHOD_NAME, mtype.descriptorString()); - // push callee parameters onto stack - builder.aload(builder.receiverSlot()) - .ldc(1) - .ldc(2L) - .ldc(3.0f) - .ldc(4.0d) - .ldc("5") - // params loaded. let's decide what method to call - .aload(builder.receiverSlot()) - // get nativeCallee field - .getfield(CLASS, CALL_NATIVE_FIELD, CALL_NATIVE_FIELD_DESC) - // if nativeCallee == false goto nonNativeLabel - .ifeq(nonNativeLabel) - // invokedynamic nativeCalleeMethod using bootstrap method - .invokedynamic(DynamicCallSiteDesc.of(dmh, NATIVE_CALLEE_METHOD_NAME, CALLEE_METHOD_DESC)) - // goto checkLabel - .goto_(checkLabel) - // label: nonNativeLabel - .labelBinding(nonNativeLabel) - // invokedynamic calleeMethod using bootstrap method - .invokedynamic(DynamicCallSiteDesc.of(dmh, CALLEE_METHOD_NAME, CALLEE_METHOD_DESC)) - .labelBinding(checkLabel) - .ldc(CallsBase.CALL_ERR_MSG) - .invokestatic(ASSERTS_CLASS, ASSERTTRUE_METHOD_NAME, ASSERTTRUE_METHOD_DESC) - // label: return - .return_(); - } - })); - Files.write(filePath, bytes, StandardOpenOption.WRITE); + @Override + public MethodVisitor visitMethod(final int access, final String name, + final String desc, final String signature, + final String[] exceptions) { + /* a code generate looks like + * 0: aload_0 + * 1: ldc #125 // int 1 + * 3: ldc2_w #126 // long 2l + * 6: ldc #128 // float 3.0f + * 8: ldc2_w #129 // double 4.0d + * 11: ldc #132 // String 5 + * 13: aload_0 + * 14: getfield #135 // Field nativeCallee:Z + * 17: ifeq 28 + * 20: invokedynamic #181, 0 // InvokeDynamic #1:calleeNative:(Lcompiler/calls/common/InvokeDynamic;IJFDLjava/lang/String;)Z + * 25: goto 33 + * 28: invokedynamic #183, 0 // InvokeDynamic #1:callee:(Lcompiler/calls/common/InvokeDynamic;IJFDLjava/lang/String;)Z + * 33: ldc #185 // String Call insuccessfull + * 35: invokestatic #191 // Method jdk/test/lib/Asserts.assertTrue:(ZLjava/lang/String;)V + * 38: return + * + * or, using java-like pseudo-code + * if (this.nativeCallee == false) { + * invokedynamic-call-return-value = invokedynamic-of-callee + * } else { + * invokedynamic-call-return-value = invokedynamic-of-nativeCallee + * } + * Asserts.assertTrue(invokedynamic-call-return-value, error-message); + * return; + */ + if (name.equals(CALLER_METHOD_NAME)) { + MethodVisitor mv = cv.visitMethod(access, name, desc, + signature, exceptions); + Label nonNativeLabel = new Label(); + Label checkLabel = new Label(); + MethodType mtype = MethodType.methodType(CallSite.class, + MethodHandles.Lookup.class, String.class, MethodType.class); + Handle bootstrap = new Handle(Opcodes.H_INVOKESTATIC, CLASS, + BOOTSTRAP_METHOD_NAME, mtype.toMethodDescriptorString()); + mv.visitCode(); + // push callee parameters onto stack + mv.visitVarInsn(Opcodes.ALOAD, 0);//push "this" + mv.visitLdcInsn(1); + mv.visitLdcInsn(2L); + mv.visitLdcInsn(3.0f); + mv.visitLdcInsn(4.0d); + mv.visitLdcInsn("5"); + // params loaded. let's decide what method to call + mv.visitVarInsn(Opcodes.ALOAD, 0); // push "this" + // get nativeCallee field + mv.visitFieldInsn(Opcodes.GETFIELD, CLASS, CALL_NATIVE_FIELD, + CALL_NATIVE_FIELD_DESC); + // if nativeCallee == false goto nonNativeLabel + mv.visitJumpInsn(Opcodes.IFEQ, nonNativeLabel); + // invokedynamic nativeCalleeMethod using bootstrap method + mv.visitInvokeDynamicInsn(NATIVE_CALLEE_METHOD_NAME, + CALLEE_METHOD_DESC, bootstrap); + // goto checkLabel + mv.visitJumpInsn(Opcodes.GOTO, checkLabel); + // label: nonNativeLabel + mv.visitLabel(nonNativeLabel); + // invokedynamic calleeMethod using bootstrap method + mv.visitInvokeDynamicInsn(CALLEE_METHOD_NAME, CALLEE_METHOD_DESC, + bootstrap); + mv.visitLabel(checkLabel); + mv.visitLdcInsn(CallsBase.CALL_ERR_MSG); + mv.visitMethodInsn(Opcodes.INVOKESTATIC, ASSERTS_CLASS, + ASSERTTRUE_METHOD_NAME, ASSERTTRUE_METHOD_DESC, false); + // label: return + mv.visitInsn(Opcodes.RETURN); + mv.visitMaxs(0, 0); + mv.visitEnd(); + return null; + } + return super.visitMethod(access, name, desc, signature, exceptions); } } diff --git a/test/hotspot/jtreg/compiler/calls/fromCompiled/CompiledInvokeDynamic2CompiledTest.java b/test/hotspot/jtreg/compiler/calls/fromCompiled/CompiledInvokeDynamic2CompiledTest.java index c20f8f4482284..914500a25d4cf 100644 --- a/test/hotspot/jtreg/compiler/calls/fromCompiled/CompiledInvokeDynamic2CompiledTest.java +++ b/test/hotspot/jtreg/compiler/calls/fromCompiled/CompiledInvokeDynamic2CompiledTest.java @@ -25,10 +25,10 @@ * @test * @summary check calls from compiled to compiled using InvokeDynamic * @library /test/lib / + * @library /testlibrary/asm * @modules java.base/jdk.internal.misc * * @build jdk.test.whitebox.WhiteBox - * @build compiler.calls.common.InvokeDynamic * @run driver compiler.calls.common.InvokeDynamicPatcher * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. diff --git a/test/hotspot/jtreg/compiler/calls/fromCompiled/CompiledInvokeDynamic2InterpretedTest.java b/test/hotspot/jtreg/compiler/calls/fromCompiled/CompiledInvokeDynamic2InterpretedTest.java index ee497d10707cb..b6f8520a90a7b 100644 --- a/test/hotspot/jtreg/compiler/calls/fromCompiled/CompiledInvokeDynamic2InterpretedTest.java +++ b/test/hotspot/jtreg/compiler/calls/fromCompiled/CompiledInvokeDynamic2InterpretedTest.java @@ -25,10 +25,10 @@ * @test * @summary check calls from compiled to interpreted using InvokeDynamic * @library /test/lib / + * @library /testlibrary/asm * @modules java.base/jdk.internal.misc * * @build jdk.test.whitebox.WhiteBox - * @build compiler.calls.common.InvokeDynamic * @run driver compiler.calls.common.InvokeDynamicPatcher * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. diff --git a/test/hotspot/jtreg/compiler/calls/fromCompiled/CompiledInvokeDynamic2NativeTest.java b/test/hotspot/jtreg/compiler/calls/fromCompiled/CompiledInvokeDynamic2NativeTest.java index 7dc2b423587b7..e334f6a15f0b8 100644 --- a/test/hotspot/jtreg/compiler/calls/fromCompiled/CompiledInvokeDynamic2NativeTest.java +++ b/test/hotspot/jtreg/compiler/calls/fromCompiled/CompiledInvokeDynamic2NativeTest.java @@ -25,10 +25,10 @@ * @test * @summary check calls from compiled to native using InvokeDynamic * @library /test/lib / + * @library /testlibrary/asm * @modules java.base/jdk.internal.misc * * @build jdk.test.whitebox.WhiteBox - * @build compiler.calls.common.InvokeDynamic * @run driver compiler.calls.common.InvokeDynamicPatcher * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. diff --git a/test/hotspot/jtreg/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2CompiledTest.java b/test/hotspot/jtreg/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2CompiledTest.java index 0ba1dd1a496be..ca626fd3b01d8 100644 --- a/test/hotspot/jtreg/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2CompiledTest.java +++ b/test/hotspot/jtreg/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2CompiledTest.java @@ -25,10 +25,10 @@ * @test * @summary check calls from interpreted to compiled using InvokeDynamic * @library /test/lib / + * @library /testlibrary/asm * @modules java.base/jdk.internal.misc * * @build jdk.test.whitebox.WhiteBox - * @build compiler.calls.common.InvokeDynamic * @run driver compiler.calls.common.InvokeDynamicPatcher * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. diff --git a/test/hotspot/jtreg/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2InterpretedTest.java b/test/hotspot/jtreg/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2InterpretedTest.java index 7ed8c683629f3..d8d877977d437 100644 --- a/test/hotspot/jtreg/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2InterpretedTest.java +++ b/test/hotspot/jtreg/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2InterpretedTest.java @@ -25,10 +25,10 @@ * @test * @summary check calls from interpreted to interpreted using InvokeDynamic * @library /test/lib / + * @library /testlibrary/asm * @modules java.base/jdk.internal.misc * * @build jdk.test.whitebox.WhiteBox - * @build compiler.calls.common.InvokeDynamic * @run driver compiler.calls.common.InvokeDynamicPatcher * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. diff --git a/test/hotspot/jtreg/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2NativeTest.java b/test/hotspot/jtreg/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2NativeTest.java index 20f94db80b125..38bca4939d4df 100644 --- a/test/hotspot/jtreg/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2NativeTest.java +++ b/test/hotspot/jtreg/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2NativeTest.java @@ -25,10 +25,10 @@ * @test * @summary check calls from interpreted to native using InvokeDynamic * @library /test/lib / + * @library /testlibrary/asm * @modules java.base/jdk.internal.misc * * @build jdk.test.whitebox.WhiteBox - * @build compiler.calls.common.InvokeDynamic * @run driver compiler.calls.common.InvokeDynamicPatcher * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. diff --git a/test/hotspot/jtreg/compiler/codegen/aes/TestAESMain.java b/test/hotspot/jtreg/compiler/codegen/aes/TestAESMain.java index 608b979e8f158..36ee43a7732a0 100644 --- a/test/hotspot/jtreg/compiler/codegen/aes/TestAESMain.java +++ b/test/hotspot/jtreg/compiler/codegen/aes/TestAESMain.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, 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 @@ -155,7 +155,7 @@ public class TestAESMain { public static void main(String[] args) { String mode = System.getProperty("mode", "CBC"); if ((mode.equals("CBC") || mode.equals("ECB")) && - !Compiler.isIntrinsicAvailable(CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION, "com.sun.crypto.provider.AES_Crypt", "implEncryptBlock", byte[].class, int.class, byte[].class, int.class)) { + !Compiler.isIntrinsicAvailable(CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION, "com.sun.crypto.provider.AESCrypt", "implEncryptBlock", byte[].class, int.class, byte[].class, int.class)) { throw new SkippedException("AES intrinsic is not available"); } if (mode.equals("GCM") && diff --git a/test/hotspot/jtreg/compiler/cpuflags/AESIntrinsicsBase.java b/test/hotspot/jtreg/compiler/cpuflags/AESIntrinsicsBase.java index 9f36aae4579b4..2ed3fd81e1cbf 100644 --- a/test/hotspot/jtreg/compiler/cpuflags/AESIntrinsicsBase.java +++ b/test/hotspot/jtreg/compiler/cpuflags/AESIntrinsicsBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ -31,7 +31,7 @@ public abstract class AESIntrinsicsBase { + ".provider\\.CipherBlockChaining::" + "(implEncrypt|implDecrypt) \\([0-9]+ bytes\\)\\s+\\(intrinsic[,\\)]"; public static final String AES_INTRINSIC = "com\\.sun\\.crypto\\" - + ".provider\\.AES_Crypt::(implEncryptBlock|implDecryptBlock) \\([0-9]+ " + + ".provider\\.AESCrypt::(implEncryptBlock|implDecryptBlock) \\([0-9]+ " + "bytes\\)\\s+\\(intrinsic[,\\)]"; public static final String USE_AES = "UseAES"; public static final String USE_AES_INTRINSICS = "UseAESIntrinsics"; diff --git a/test/hotspot/jtreg/compiler/exceptions/IllegalAccessInCatch.jasm b/test/hotspot/jtreg/compiler/exceptions/IllegalAccessInCatch.jasm deleted file mode 100644 index beeffa69a971e..0000000000000 --- a/test/hotspot/jtreg/compiler/exceptions/IllegalAccessInCatch.jasm +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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. - */ - -super class IllegalAccessInCatch - version 52:0 -{ - /* - static int test() { - try { - return 1 / 0; - } catch (jdk.internal.agent.AgentConfigurationError e1) { - try { - return 0; - } catch (IllegalAccessError e2) { - return 1; - } - } - } - */ - static Method test:"()I" - stack 2 locals 1 - { - iconst_1; - iconst_0; - try t0; - idiv; - endtry t0; - ireturn; - catch t0 jdk/internal/agent/AgentConfigurationError; // loadable but not accessible from unnamed module - stack_frame_type full; - stack_map class java/lang/Throwable; - try t1; - iconst_0; - ireturn; - endtry t1; - catch t1 java/lang/IllegalAccessError; - stack_frame_type full; - stack_map class java/lang/Throwable; - iconst_1; - ireturn; - } -} diff --git a/test/hotspot/jtreg/compiler/exceptions/TestAccessErrorInCatch.java b/test/hotspot/jtreg/compiler/exceptions/TestAccessErrorInCatch.java deleted file mode 100644 index 46541d760169f..0000000000000 --- a/test/hotspot/jtreg/compiler/exceptions/TestAccessErrorInCatch.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 8367002 - * @summary Compilers might not generate handlers for recursive exceptions - * - * @compile IllegalAccessInCatch.jasm - * @run main/othervm -Xbatch - * -XX:CompileCommand=compileonly,IllegalAccessInCatch*::test - * -XX:-TieredCompilation - * TestAccessErrorInCatch - * @run main/othervm -Xbatch - * -XX:CompileCommand=compileonly,IllegalAccessInCatch*::test - * -XX:TieredStopAtLevel=3 - * TestAccessErrorInCatch - */ - -import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodHandles; -import java.lang.invoke.MethodType; - -import java.nio.file.Files; -import java.nio.file.FileSystems; -import java.nio.file.Path; -import java.nio.file.Paths; - -public class TestAccessErrorInCatch { - - public static void main(String[] args) throws Throwable { - Path TEST_CLASSES_DIR = FileSystems.getDefault().getPath(System.getProperty("test.classes")); - byte[] bytes = Files.readAllBytes(TEST_CLASSES_DIR.resolve("IllegalAccessInCatch.class")); - - var l = MethodHandles.lookup().defineHiddenClass(bytes, true); - Class anonClass = l.lookupClass(); - MethodHandle mh = l.findStatic(anonClass, "test", MethodType.methodType(int.class)); - for (int i = 0; i < 16_000; i++) { - invoke(mh); - } - System.out.println(invoke(mh)); - } - - private static int invoke(MethodHandle mh) throws Throwable { - return (int) mh.invokeExact(); - } -} diff --git a/test/hotspot/jtreg/compiler/gcbarriers/TestG1BarrierGeneration.java b/test/hotspot/jtreg/compiler/gcbarriers/TestG1BarrierGeneration.java index c1e2dd7a112f0..01e015d50cb74 100644 --- a/test/hotspot/jtreg/compiler/gcbarriers/TestG1BarrierGeneration.java +++ b/test/hotspot/jtreg/compiler/gcbarriers/TestG1BarrierGeneration.java @@ -880,16 +880,6 @@ public void runAtomicTests() { Asserts.assertEquals(oldVal, oldVal2); Asserts.assertEquals(o.f, newVal); } - { - Outer o = new Outer(); - Object oldVal = new Object(); - o.f = oldVal; - Object cmpVal = new Object(); - Object newVal = new Object(); - Object oldVal2 = testCompareAndExchange(o, cmpVal, newVal); - Asserts.assertEquals(oldVal2, oldVal); - Asserts.assertEquals(o.f, oldVal); - } { Outer o = new Outer(); Object oldVal = new Object(); @@ -899,16 +889,6 @@ public void runAtomicTests() { Asserts.assertTrue(b); Asserts.assertEquals(o.f, newVal); } - { - Outer o = new Outer(); - Object oldVal = new Object(); - o.f = oldVal; - Object cmpVal = new Object(); - Object newVal = new Object(); - boolean b = testCompareAndSwap(o, cmpVal, newVal); - Asserts.assertFalse(b); - Asserts.assertEquals(o.f, oldVal); - } { Outer o = new Outer(); Object oldVal = new Object(); diff --git a/test/hotspot/jtreg/compiler/jsr292/RedefineMethodUsedByMultipleMethodHandles.java b/test/hotspot/jtreg/compiler/jsr292/RedefineMethodUsedByMultipleMethodHandles.java index 9a74806e621fb..769863880f234 100644 --- a/test/hotspot/jtreg/compiler/jsr292/RedefineMethodUsedByMultipleMethodHandles.java +++ b/test/hotspot/jtreg/compiler/jsr292/RedefineMethodUsedByMultipleMethodHandles.java @@ -21,11 +21,12 @@ * questions. */ -/* +/** * @test * @bug 8042235 * @summary redefining method used by multiple MethodHandles crashes VM * @library / + * @library /testlibrary/asm * @modules java.compiler * java.instrument * jdk.attach @@ -36,13 +37,15 @@ package compiler.jsr292; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; -import java.lang.classfile.ClassFile; -import java.lang.classfile.ClassHierarchyResolver; -import java.lang.classfile.ClassTransform; -import java.lang.classfile.instruction.ConstantInstruction; import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.IllegalClassFormatException; import java.lang.instrument.Instrumentation; @@ -156,15 +159,28 @@ static class FooTransformer implements ClassFileTransformer { public byte[] transform(ClassLoader cl, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { if (Foo.class.equals(classBeingRedefined)) { System.out.println("redefining " + classBeingRedefined); - var context = ClassFile.of(ClassFile.ClassHierarchyResolverOption.of(ClassHierarchyResolver.ofResourceParsing(cl))); - return context.transformClass(context.parse(classfileBuffer), ClassTransform.transformingMethodBodies((codeBuilder, codeElement) -> { - if (codeElement instanceof ConstantInstruction.LoadConstantInstruction ldc) { - System.out.println("replacing \"" + ldc.constantEntry().constantValue() + "\" with \"bar\""); - codeBuilder.ldc("bar"); - } else { - codeBuilder.with(codeElement); + ClassReader cr = new ClassReader(classfileBuffer); + ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES); + ClassVisitor adapter = new ClassVisitor(Opcodes.ASM5, cw) { + @Override + public MethodVisitor visitMethod(int access, String base, String desc, String signature, String[] exceptions) { + MethodVisitor mv = cv.visitMethod(access, base, desc, signature, exceptions); + if (mv != null) { + mv = new MethodVisitor(Opcodes.ASM5, mv) { + @Override + public void visitLdcInsn(Object cst) { + System.out.println("replacing \"" + cst + "\" with \"bar\""); + mv.visitLdcInsn("bar"); + } + }; + } + return mv; } - })); + }; + + cr.accept(adapter, ClassReader.SKIP_FRAMES); + cw.visitEnd(); + return cw.toByteArray(); } return classfileBuffer; } diff --git a/test/hotspot/jtreg/compiler/jvmci/common/CTVMUtilities.java b/test/hotspot/jtreg/compiler/jvmci/common/CTVMUtilities.java index c98d9944c809a..95917f6d9439d 100644 --- a/test/hotspot/jtreg/compiler/jvmci/common/CTVMUtilities.java +++ b/test/hotspot/jtreg/compiler/jvmci/common/CTVMUtilities.java @@ -23,26 +23,28 @@ package compiler.jvmci.common; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Label; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.tree.ClassNode; +import jdk.test.lib.Utils; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.hotspot.CompilerToVMHelper; +import jdk.vm.ci.hotspot.HotSpotNmethod; import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import java.io.IOException; -import java.lang.classfile.Attributes; -import java.lang.classfile.ClassFile; -import java.lang.classfile.ClassModel; -import java.lang.classfile.MethodModel; -import java.lang.constant.ClassDesc; -import java.lang.constant.ConstantDescs; -import java.lang.constant.MethodTypeDesc; -import java.lang.invoke.MethodType; import java.lang.reflect.Constructor; import java.lang.reflect.Executable; +import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.util.Arrays; -import java.util.List; +import java.lang.reflect.Parameter; +import java.util.HashMap; import java.util.Map; import java.util.TreeMap; @@ -69,55 +71,76 @@ public static InstalledCode getInstalledCode(ResolvedJavaMethod method, String n } public static Map getBciToLineNumber(Executable method) { - ClassModel classModel = findClassBytes(method.getDeclaringClass()); - MethodModel methodModel = findMethod(classModel, method); - if (methodModel == null) - return Map.of(); - - var foundLineNumberTable = methodModel.code().flatMap(code -> - code.findAttribute(Attributes.lineNumberTable())); - if (foundLineNumberTable.isEmpty()) { - boolean isEmptyMethod = Modifier.isAbstract(method.getModifiers()) - || Modifier.isNative(method.getModifiers()); - if (!isEmptyMethod) { - throw new Error(method + " doesn't contains the line numbers table " - + "(the method marked neither abstract nor native)"); - } - return Map.of(); + Map lineNumbers = new TreeMap<>(); + Class aClass = method.getDeclaringClass(); + ClassReader cr; + try { + Module aModule = aClass.getModule(); + String name = aClass.getName(); + cr = new ClassReader(aModule.getResourceAsStream( + name.replace('.', '/') + ".class")); + } catch (IOException e) { + throw new Error("TEST BUG: can read " + aClass.getName() + " : " + e, e); } + ClassNode cn = new ClassNode(); + cr.accept(cn, ClassReader.EXPAND_FRAMES); - Map lineNumbers = new TreeMap<>(); - foundLineNumberTable.get().lineNumbers().forEach(ln -> - lineNumbers.put(ln.startPc(), ln.lineNumber())); + Map labels = new HashMap<>(); + ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); + ClassVisitor cv = new ClassVisitorForLabels(cw, labels, method); + cr.accept(cv, ClassReader.EXPAND_FRAMES); + labels.forEach((k, v) -> lineNumbers.put(k.getOffset(), v)); + boolean isEmptyMethod = Modifier.isAbstract(method.getModifiers()) + || Modifier.isNative(method.getModifiers()); + if (lineNumbers.isEmpty() && !isEmptyMethod) { + throw new Error(method + " doesn't contains the line numbers table " + +"(the method marked neither abstract nor native)"); + } return lineNumbers; } - // Finds the ClassFile API model of a given class, or fail with an Error. - public static ClassModel findClassBytes(Class clazz) { - String binaryName = clazz.getName(); - byte[] fileBytes; - try (var inputStream = clazz.getModule().getResourceAsStream( - binaryName.replace('.', '/') + ".class")) { - fileBytes = inputStream.readAllBytes(); - } catch (IOException e) { - throw new Error("TEST BUG: cannot read " + binaryName, e); - } - return ClassFile.of().parse(fileBytes); - } + private static class ClassVisitorForLabels extends ClassVisitor { + private final Map lineNumbers; + private final String targetName; + private final String targetDesc; + + public ClassVisitorForLabels(ClassWriter cw, Map lines, + Executable target) { + super(Opcodes.ASM7, cw); + this.lineNumbers = lines; - // Finds a matching method in a class model, or null if none match. - public static MethodModel findMethod(ClassModel classModel, Executable method) { - MethodTypeDesc methodType = MethodType.methodType( - method instanceof Method m ? m.getReturnType() : void.class, - method.getParameterTypes()).describeConstable().orElseThrow(); - String methodName = method instanceof Method m ? m.getName() : ConstantDescs.INIT_NAME; + StringBuilder builder = new StringBuilder("("); + for (Parameter parameter : target.getParameters()) { + builder.append(Utils.toJVMTypeSignature(parameter.getType())); + } + builder.append(")"); + if (target instanceof Constructor) { + targetName = ""; + builder.append("V"); + } else { + targetName = target.getName(); + builder.append(Utils.toJVMTypeSignature( + ((Method) target).getReturnType())); + } + targetDesc = builder.toString(); + } - for (var methodModel : classModel.methods()) { - if (methodModel.methodName().equalsString(methodName) - && methodModel.methodType().isMethodType(methodType)) { - return methodModel; + @Override + public final MethodVisitor visitMethod(int access, String name, + String desc, String signature, + String[] exceptions) { + MethodVisitor mv = cv.visitMethod(access, name, desc, signature, + exceptions); + if (targetDesc.equals(desc) && targetName.equals(name)) { + return new MethodVisitor(Opcodes.ASM7, mv) { + @Override + public void visitLineNumber(int i, Label label) { + super.visitLineNumber(i, label); + lineNumbers.put(label, i); + } + }; } + return mv; } - return null; } } diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestHotSpotJVMCIRuntime.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestHotSpotJVMCIRuntime.java index e62de99f36687..e5d1da81309af 100644 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestHotSpotJVMCIRuntime.java +++ b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestHotSpotJVMCIRuntime.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2023, 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 @@ -114,7 +114,7 @@ public void getIntrinsificationTrustPredicateTest() throws Exception { VirtualObjectLayoutTest.class, TestHotSpotJVMCIRuntime.class)); try { - classes.add(Class.forName("com.sun.crypto.provider.AES_Crypt")); + classes.add(Class.forName("com.sun.crypto.provider.AESCrypt")); classes.add(Class.forName("com.sun.crypto.provider.CipherBlockChaining")); } catch (ClassNotFoundException e) { // Extension classes not available diff --git a/test/hotspot/jtreg/compiler/lib/generators/UniformDoubleGenerator.java b/test/hotspot/jtreg/compiler/lib/generators/UniformDoubleGenerator.java index b5729aeec7d6f..d160bf319d818 100644 --- a/test/hotspot/jtreg/compiler/lib/generators/UniformDoubleGenerator.java +++ b/test/hotspot/jtreg/compiler/lib/generators/UniformDoubleGenerator.java @@ -35,9 +35,6 @@ final class UniformDoubleGenerator extends UniformIntersectionRestrictableGenera */ public UniformDoubleGenerator(Generators g, double lo, double hi) { super(g, lo, hi); - if (Double.compare(lo, hi) >= 0) { - throw new EmptyGeneratorException(); - } } @Override diff --git a/test/hotspot/jtreg/compiler/lib/generators/UniformFloatGenerator.java b/test/hotspot/jtreg/compiler/lib/generators/UniformFloatGenerator.java index 4405b12061986..1b72ad5adc952 100644 --- a/test/hotspot/jtreg/compiler/lib/generators/UniformFloatGenerator.java +++ b/test/hotspot/jtreg/compiler/lib/generators/UniformFloatGenerator.java @@ -35,9 +35,6 @@ final class UniformFloatGenerator extends UniformIntersectionRestrictableGenerat */ public UniformFloatGenerator(Generators g, float lo, float hi) { super(g, lo, hi); - if (Float.compare(lo, hi) >= 0) { - throw new EmptyGeneratorException(); - } } @Override diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index f0f7aaf383615..99a289476ec4d 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -2840,36 +2840,6 @@ public class IRNode { vectorNode(EXPAND_BITS_VL, "ExpandBitsV", TYPE_LONG); } - public static final String COMPRESS_VB = VECTOR_PREFIX + "COMPRESS_VB" + POSTFIX; - static { - vectorNode(COMPRESS_VB, "CompressV", TYPE_BYTE); - } - - public static final String COMPRESS_VS = VECTOR_PREFIX + "COMPRESS_VS" + POSTFIX; - static { - vectorNode(COMPRESS_VS, "CompressV", TYPE_SHORT); - } - - public static final String COMPRESS_VI = VECTOR_PREFIX + "COMPRESS_VI" + POSTFIX; - static { - vectorNode(COMPRESS_VI, "CompressV", TYPE_INT); - } - - public static final String COMPRESS_VL = VECTOR_PREFIX + "COMPRESS_VL" + POSTFIX; - static { - vectorNode(COMPRESS_VL, "CompressV", TYPE_LONG); - } - - public static final String COMPRESS_VF = VECTOR_PREFIX + "COMPRESS_VF" + POSTFIX; - static { - vectorNode(COMPRESS_VF, "CompressV", TYPE_FLOAT); - } - - public static final String COMPRESS_VD = VECTOR_PREFIX + "COMPRESS_VD" + POSTFIX; - static { - vectorNode(COMPRESS_VD, "CompressV", TYPE_DOUBLE); - } - public static final String EXPAND_VB = VECTOR_PREFIX + "EXPAND_VB" + POSTFIX; static { vectorNode(EXPAND_VB, "ExpandV", TYPE_BYTE); diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java index 09e291ce5a480..85c52ef33dab1 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java @@ -327,10 +327,8 @@ public TestFramework addScenarios(Scenario... scenarios) { for (Scenario scenario : scenarios) { int scenarioIndex = scenario.getIndex(); - if (!scenarioIndices.add(scenarioIndex)) { - TestFormat.failNoThrow("Cannot define two scenarios with the same index " + scenarioIndex); - continue; - } + TestFormat.checkNoThrow(scenarioIndices.add(scenarioIndex), + "Cannot define two scenarios with the same index " + scenarioIndex); this.scenarios.add(scenario); } TestFormat.throwIfAnyFailures(); @@ -338,12 +336,9 @@ public TestFramework addScenarios(Scenario... scenarios) { } /** - * Add the cross-product (cartesian product) of sets of flags as Scenarios. Unlike when constructing + * Add the cross-product (cartesian product) of sets of flags as Scenarios. Unlike when when constructing * scenarios directly a string can contain multiple flags separated with a space. This allows grouping - * flags that have to be specified together. Further, an empty string in a set stands in for "no flag". - *

    - * Passing a single set will create a scenario for each of the provided flags in the set (i.e. the same as - * passing an additional set with an empty string only). + * flags that have to be specified togeher. Further, an empty string in a set stands in for "no flag". *

    * Example: *

    @@ -360,7 +355,7 @@ public TestFramework addScenarios(Scenario... scenarios) {
          *     Scenario(5, "-Xbatch -XX:-TieredCompilation", "-XX:+UseNewCode2")
          * 
    * - * @param flagSets sets of flags to generate the cross product for. + * @param sets sets of flags to generate the cross product for. * @return the same framework instance. */ @SafeVarargs @@ -381,7 +376,7 @@ final public TestFramework addCrossProductScenarios(Set... flagSets) { Stream> crossProduct = Arrays.stream(flagSets) .reduce( - Stream.of(Collections.emptyList()), // Initialize Stream> acc with a Stream containing an empty list of Strings. + Stream.of(Collections.emptyList()), // Initialize Stream> acc with a Stream containing an empty list of Strings. (Stream> acc, Set set) -> acc.flatMap(lAcc -> // For each List> lAcc in acc... set.stream().map(flag -> { // ...and each flag in the current set... @@ -389,19 +384,19 @@ final public TestFramework addCrossProductScenarios(Set... flagSets) { newList.add(flag); // ...and append the flag. return newList; }) // This results in one List> for each lAcc... - ), // ...that get flattened into one big List>. - Stream::concat); // combiner; if any reduction steps are executed in parallel, just concat two streams. + ), // ...that get flattend into one big List>. + (a, b) -> Stream.concat(a, b)); // combiner; if any reduction steps are executed in parallel, just concat two streams. Scenario[] newScenarios = crossProduct .map(flags -> new Scenario( // For each List flags in crossProduct create a new Scenario. idx.getAndIncrement(), flags.stream() // Process flags - .map(s -> Set.of(s.split("[ ]"))) // Split multiple flags in the same string into separate strings. + .map(s -> Set.of(s.split("[ ]"))) // Split muliple flags in the same string into separate strings. .flatMap(Collection::stream) // Flatten the Stream> into Stream>. .filter(s -> !s.isEmpty()) // Remove empty string flags. - .toList() + .collect(Collectors.toList()) .toArray(new String[0]))) - .toList().toArray(new Scenario[0]); + .collect(Collectors.toList()).toArray(new Scenario[0]); return addScenarios(newScenarios); } diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.java b/test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.java index daa2b9765f8e0..c05124edcd78c 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/test/IREncodingPrinter.java @@ -106,7 +106,6 @@ public class IREncodingPrinter { "avx512_fp16", "avx512_vnni", "avx512_vbmi", - "avx512_vbmi2", "avx10_2", "bmi2", // AArch64 diff --git a/test/hotspot/jtreg/compiler/loopopts/TestReassociateInvariants.java b/test/hotspot/jtreg/compiler/loopopts/TestReassociateInvariants.java deleted file mode 100644 index d03cb4e85676d..0000000000000 --- a/test/hotspot/jtreg/compiler/loopopts/TestReassociateInvariants.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2025 IBM Corporation. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/** - * @test - * @bug 8369258 - * @summary C2: enable ReassociateInvariants for all loop types - * @library /test/lib / - * @run driver compiler.loopopts.TestReassociateInvariants - */ - -package compiler.loopopts; - - -import compiler.lib.ir_framework.*; - -import java.util.Objects; - -public class TestReassociateInvariants { - private static long longStart = 0; - private static long longStop = 1000; - private static int intStart = 0; - private static int intStop = 1000; - - public static void main(String[] args) { - TestFramework.runWithFlags("-XX:-ShortRunningLongLoop"); - } - - // The IR framework is not powerful enough to directly check - // wether invariants are moved out of a loop so tests below rely on - // some side effect that can be observed by the IR framework. - - // Once a + (b + i) is transformed into i + (a + b), the a + b - // before the loop and the one from inside the loop common and one - // Add is removed. - @Test - @IR(counts = {IRNode.ADD_I, "3"}) - @Arguments(values = { Argument.NUMBER_42, Argument.NUMBER_42 }) - public int test1(int a, int b) { - int v = a + b; - for (int i = 1; i < 100; i *= 2) { - v += a + (b + i); - } - return v; - } - - // Range Check Elimination only happens once a + (b + i) is - // transformed into i + (a + b). With the range check eliminated, - // the loop can be removed. At this point, C2 doesn't support - // removal of long counted loop. The long counted loop is - // transformed into a loop nest with an inner int counted - // loop. That one is empty and is removed. - @Test - @IR(failOn = { IRNode.COUNTED_LOOP, IRNode.LONG_COUNTED_LOOP }) - @IR(counts = { IRNode.LOOP, "1" }) - @Arguments(values = { Argument.NUMBER_42, Argument.NUMBER_42 }) - public void test2(long a, long b) { - for (long i = longStart; i < longStop; i++) { - Objects.checkIndex(a + (b + i), Long.MAX_VALUE); - } - } - - // Same here for an int counted loop with long range checks - @Test - @IR(failOn = { IRNode.COUNTED_LOOP }) - @IR(counts = { IRNode.LOOP, "1" }) - @Arguments(values = { Argument.NUMBER_42, Argument.NUMBER_42 }) - public void test3(long a, long b) { - for (int i = intStart; i < intStop; i++) { - Objects.checkIndex(a + (b + i), Long.MAX_VALUE); - } - } -} diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestAliasingFuzzer.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestAliasingFuzzer.java index 62e474ecb2c67..30e1f1c061950 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestAliasingFuzzer.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestAliasingFuzzer.java @@ -112,10 +112,7 @@ * memory and split ranges. But we could alternate between same memory * and split ranges, and then different memory but overlapping ranges. * This would also be never aliasing. - * - Generate cases that would catch bugs like JDK-8369902: - * - Large long constants, or scales. Probably only possible for MemorySegment. - * - Large number of invar, and reuse of invar so that they could cancle - * to zero, and need to be filtered out. + * */ public class TestAliasingFuzzer { private static final Random RANDOM = Utils.getRandomInstance(); diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestDoNotFilterNaNSummands.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestDoNotFilterNaNSummands.java deleted file mode 100644 index 93a1f0b56a8b8..0000000000000 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestDoNotFilterNaNSummands.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 8369902 - * @summary Bug in MemPointerParser::canonicalize_raw_summands let to wrong result, because a - * NaN summand was filtered out, instead of making the MemPointer / VPointer invalid. - * @run main/othervm - * -XX:+IgnoreUnrecognizedVMOptions - * -XX:CompileCommand=compileonly,*TestDoNotFilterNaNSummands::test - * -Xbatch - * compiler.loopopts.superword.TestDoNotFilterNaNSummands - * @run main compiler.loopopts.superword.TestDoNotFilterNaNSummands - */ - -package compiler.loopopts.superword; - -// This was the test found by the fuzzer. If you are looking for a simpler example with the same issue, -// please look at TestMemorySegmentFilterSummands::test2. -public class TestDoNotFilterNaNSummands { - static final int N = 100; - static int zero = 0; - - static int[] test() { - int x = -4; - int aI[] = new int[N]; - for (int k = 0; k < N; k++) { - // Note that x is always "-4", and N is a compile time constant. The modulo "%" - // gets optimized with magic numbers and shift/mul/sub trick, in the long domain, - // which somehow creates some large long constant that cannot be represented - // as an int. - int idx = (x >>> 1) % N; - // This is the CountedLoop that we may try to auto vectorize. - // We have a linear access (i) and a constant index access (idx), which eventually - // cross, so there is aliasing. If there is vectorization with an aliasing runtime - // check, this check must fail. - for (int i = 1; i < 63; i++) { - aI[i] = 2; - // The MemPointer / VPointer for the accesses below contain a large constant - // long constant offset that cannot be represented as an int, so the scaleL - // NoOverflowInt becomes NaN. In MemPointerParser::canonicalize_raw_summands - // we are supposed to filter out zero summands, but since we WRONGLY filtered - // out NaNs instead, this summand got filtered out, and later we did not detect - // that the MemPointer contains a NaN. Instead, we just get a "valid" looking - // VPointer, and generate runtime checks that are missing the long constant - // offset, leading to wrong decisions, and hence vectorization even though - // we have aliasing. This means that the accesses from above and below get - // reordered in an illegal way, leading to wrong results. - aI[idx] += 1; - } - for (int i = 0; i < 100; i++) { - // It is a no-op, but the compiler can't know statically that zero=0. - // Seems to be required in the graph, no idea why. - x >>= zero; - } - } - return aI; - } - - // Use the sum as an easy way to compare the results. - public static int sum(int[] aI) { - int sum = 0; - for (int i = 0; i < aI.length; i++) { sum += aI[i]; } - return sum; - } - - public static void main(String[] args) { - // Run once, hopefully before compilation, so get interpreter results. - int[] aIG = test(); - int gold = sum(aIG); - - // Repeat execution, until eventually compilation happens, compare - // compiler results to interpreter results. - for (int k = 0; k < 1000; k++) { - int[] aI = test(); - int val = sum(aI); - if (gold != val) { - System.out.println("Detected wrong result, printing values of arrays:"); - for (int i = 0; i < aI.length; i++) { - System.out.println("at " + i + ": " + aIG[i] + " vs " + aI[i]); - } - throw new RuntimeException("wrong result: " + gold + " " + val); - } - } - } -} diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegmentFilterSummands.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegmentFilterSummands.java deleted file mode 100644 index 355d8d5383ccd..0000000000000 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegmentFilterSummands.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * 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.loopopts.superword; - -import java.lang.foreign.*; -import java.util.Set; - -import compiler.lib.ir_framework.*; -import compiler.lib.verify.*; - -/* - * @test - * @bug 8369902 - * @summary Bug in MemPointerParser::canonicalize_raw_summands let to wrong results or assert. - * @library /test/lib / - * @run driver compiler.loopopts.superword.TestMemorySegmentFilterSummands - */ - -public class TestMemorySegmentFilterSummands { - - static long init = 1000; - static long limit = 9000; - - static long invar0 = 0; - static long invar1 = 0; - static long invar2 = 0; - static long invar3 = 0; - static long invar4 = 0; - static long invarX = 0; - - public static final long BIG = 0x200000000L; - public static long big = -BIG; - - static MemorySegment a1 = Arena.ofAuto().allocate(10_000); - static MemorySegment b1 = Arena.ofAuto().allocate(10_000); - static { - for (long i = init; i < limit; i++) { - a1.set(ValueLayout.JAVA_BYTE, i, (byte)((i & 0xf) + 1)); - } - } - - static MemorySegment a2 = MemorySegment.ofArray(new byte[40_000]); - static MemorySegment b2 = a2; - - public static void main(String[] args) { - TestFramework f = new TestFramework(); - f.addFlags("-XX:+IgnoreUnrecognizedVMOptions"); - f.addCrossProductScenarios(Set.of("-XX:-AlignVector", "-XX:+AlignVector"), - Set.of("-XX:-ShortRunningLongLoop", "-XX:+ShortRunningLoop")); - f.start(); - } - - @Test - @IR(counts = {IRNode.STORE_VECTOR, "> 0", - IRNode.LOAD_VECTOR_B, "> 0", - ".*multiversion.*", "= 0"}, // AutoVectorization Predicate SUFFICES, there is no aliasing - phase = CompilePhase.PRINT_IDEAL, - applyIfPlatform = {"64-bit", "true"}, - applyIf = {"AlignVector", "false"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) - public static void test1() { - long invar = 0; - invar += invarX; // cancles out with above - invar += invar0; - invar += invar1; - invar += invar2; - invar += invar3; - invar += invar4; - invar -= invarX; // cancles out with above - // invar contains a raw summand for invarX, which has a scaleL=0. It needs to be filtered out. - // The two occurances of invarX are conveniently put in a long chain, so that IGVN cannot see - // that they cancle out, so that they are not optimized out before loop-opts. - for (long i = init; i < limit; i++) { - byte v = a1.get(ValueLayout.JAVA_BYTE, i + invar); - b1.set(ValueLayout.JAVA_BYTE, i + invar, v); - } - } - - @Check(test = "test1") - static void check1() { - Verify.checkEQ(a1, b1); - } - - @Test - @IR(failOn = {IRNode.STORE_VECTOR}) - // This test could in principle show vectorization, but it would probably need to do some special - // tricks to only vectorize around the overlap. Still, it could happen that at some point we end - // up multiversioning, and having a vectorized loop that is never entered. - // - // For now, the long constant BIG leads to an invalid VPointer, which means we do not vectorize. - static void test2() { - // At runtime, "BIG + big" is zero. But BIG is a long constant that cannot be represented as - // an int, and so the scaleL NoOverflowInt is a NaN. We should not filter it out from the summands, - // but instead make the MemPointer / VPointer invalid, which prevents vectorization. - long adr = 4L * 5000 + BIG + big; - - for (long i = init; i < limit; i++) { - // The reference to a2 iterates linearly, while the reference to "b2" stays at the same adr. - // But the two alias: in the middle of the "a2" range it crosses over "b2" adr, so the - // aliasing runtime check (if we generate one) should fail. But if "BIG" is just filtered - // out from the summands, we instead just create a runtime check without it, which leads - // to a wrong answer, and the check does not fail, and we get wrong results. - a2.set(ValueLayout.JAVA_INT_UNALIGNED, 4L * i, 0); - int v = b2.get(ValueLayout.JAVA_INT_UNALIGNED, adr); - b2.set(ValueLayout.JAVA_INT_UNALIGNED, adr, v + 1); - } - } - - @Check(test = "test2") - static void check2() { - int s = 0; - for (long i = init; i < limit; i++) { - s += a2.get(ValueLayout.JAVA_INT_UNALIGNED, 4L * i); - } - if (s != 4000) { - throw new RuntimeException("wrong value"); - } - } -} diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegment_ReassociateInvariants1.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegment_8360204.java similarity index 83% rename from test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegment_ReassociateInvariants1.java rename to test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegment_8360204.java index 57864a09d690b..ecefcec8afa81 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegment_ReassociateInvariants1.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegment_8360204.java @@ -31,16 +31,16 @@ /* * @test - * @bug 8324751 8369258 + * @bug 8324751 * @summary Reported issue: JDK-8360204: C2 SuperWord: missing RCE with MemorySegment.getAtIndex * The examples are generated from TestAliasingFuzzer.java * So if you see something change here, you may want to investigate if we * can also tighten up the IR rules there. * @library /test/lib / - * @run driver compiler.loopopts.superword.TestMemorySegment_ReassociateInvariants1 + * @run driver compiler.loopopts.superword.TestMemorySegment_8360204 */ -public class TestMemorySegment_ReassociateInvariants1 { +public class TestMemorySegment_8360204 { public static MemorySegment a = Arena.ofAuto().allocate(10_000); public static MemorySegment b = Arena.ofAuto().allocate(10_000); @@ -67,13 +67,20 @@ static Object[] setup() { @Arguments(setup = "setup") @IR(counts = {IRNode.LOAD_VECTOR_I, "= 0", IRNode.STORE_VECTOR, "= 0", - ".*multiversion.*", "= 0"}, + ".*multiversion.*", "> 0"}, // Sadly, we now multiversion phase = CompilePhase.PRINT_IDEAL, applyIfPlatform = {"64-bit", "true"}, applyIf = {"AlignVector", "false"}, applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + // There is no aliasing, so we should compile without multiversioning. + // But currently, there seems to be some issue with RCE, we peel and lose the predicate. + // Then we multiversion. // We could imagine that this would eventually vectorize, but since one counts up, and the other down, // we would have to implement shuffle first. + // + // If you see this IR rule fail: investigate JDK-8360204, possibly close it and fix this IR rule! + // Also: consider renaming the file to something more descriptive: what have you fixed with this? + // And: you may now be able to tighten IR rules in TestAliasingFuzzer.java public static void test(MemorySegment container_0, long invar0_0, MemorySegment container_1, long invar0_1, long ivLo, long ivHi) { for (long i = ivLo; i < ivHi; i+=1) { var v = container_0.getAtIndex(ValueLayout.JAVA_INT_UNALIGNED, 19125L + 1L * i + 1L * invar0_0 + 0L * invar0_1159 + 1L * invar1_1159); diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegment_ReassociateInvariants2.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegment_8365982.java similarity index 82% rename from test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegment_ReassociateInvariants2.java rename to test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegment_8365982.java index 6f1590f5e1919..65fd386117451 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegment_ReassociateInvariants2.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegment_8365982.java @@ -31,16 +31,16 @@ /* * @test - * @bug 8324751 8369258 + * @bug 8324751 * @summary Reported issue: JDK-8365982: C2 SuperWord: missing RCE / strange Multiversioning with MemorySegment.set * The examples are generated from TestAliasingFuzzer.java * So if you see something change here, you may want to investigate if we * can also tighten up the IR rules there. * @library /test/lib / - * @run driver compiler.loopopts.superword.TestMemorySegment_ReassociateInvariants2 + * @run driver compiler.loopopts.superword.TestMemorySegment_8365982 */ -public class TestMemorySegment_ReassociateInvariants2 { +public class TestMemorySegment_8365982 { public static MemorySegment a = MemorySegment.ofArray(new short[100_000]); public static MemorySegment b = MemorySegment.ofArray(new short[100_000]); @@ -76,11 +76,19 @@ static Object[] setup() { // @IR(counts = {IRNode.STORE_VECTOR, "> 0", IRNode.REPLICATE_S, "> 0", - ".*multiversion.*", "= 0"}, + ".*multiversion.*", "> 0"}, // Bad: Sadly, we now multiversion phase = CompilePhase.PRINT_IDEAL, applyIfPlatform = {"64-bit", "true"}, applyIfAnd = {"AlignVector", "false", "ShortRunningLongLoop", "true"}, applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + // Some but not all predicates are RCE'd at the beginning. After unrolling, we multiversion (why?). + // After PreMainPost, we can do more RangeCheck. Now the main-loop of the multiversion_fast loop + // does not have any range checks any more. + // Now it vectorizes. That's good, but we should be able to vectorize without multiversioning. + // + // If you see this IR rule fail: investigate JDK-8365982, possibly close it and fix this IR rule! + // Also: consider renaming the file to something more descriptive: what have you fixed with this? + // And: you may now be able to tighten IR rules in TestAliasingFuzzer.java public static void test(MemorySegment container_0, long invar0_0, MemorySegment container_1, long invar0_1, long ivLo, long ivHi) { for (long i = ivHi-1; i >= ivLo; i-=1) { container_0.set(ValueLayout.JAVA_CHAR_UNALIGNED, -47143L + -2L * i + -2L * invar0_0 + -1L * invar0_853 + -1L * invar1_853 + 0L * invar2_853, (char)0x0102030405060708L); diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestMultiversionSlowProjReplacementAndGetCtrl.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestMultiversionSlowProjReplacementAndGetCtrl.java deleted file mode 100644 index 6d2249cc15cf8..0000000000000 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestMultiversionSlowProjReplacementAndGetCtrl.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 8369898 - * @summary Bug in PhaseIdealLoop::create_new_if_for_multiversion, that messed up the - * _loop_or_ctrl data structure while doing SuperWord for a first loop, and - * then get_ctrl asserted for a second loop that was also SuperWord-ed in the - * same loop-opts-phase. - * @run main/othervm - * -XX:CompileCommand=compileonly,*TestMultiversionSlowProjReplacementAndGetCtrl::test - * -XX:CompileCommand=exclude,*TestMultiversionSlowProjReplacementAndGetCtrl::dontinline - * -XX:-TieredCompilation - * -Xbatch - * compiler.loopopts.superword.TestMultiversionSlowProjReplacementAndGetCtrl - * @run main compiler.loopopts.superword.TestMultiversionSlowProjReplacementAndGetCtrl - */ - -package compiler.loopopts.superword; - -public class TestMultiversionSlowProjReplacementAndGetCtrl { - static final int N = 400; - - static void dontinline() {} - - static long test() { - int x = 0; - int arrayI[] = new int[N]; - byte[] arrayB = new byte[N]; - dontinline(); - // CallStaticJava for dontinline - // -> memory Proj - // -> it is used in both the k-indexed and j-indexed loops by their loads/stores. - for (int k = 8; k < 92; ++k) { - // Loop here is multiversioned, and eventually we insert an aliasing runtime check. - // This means that a StoreN (with mem input Proj from above) has its ctrl changed - // from the old multiversion_if_proj to a new region. We have to be careful to update - // the _loop_or_ctrl side-table so that get_ctrl for StoreN is sane. - // - // Below is some nested loop material I could not reduce further. Maybe because - // of loop-opts phase timing. Because we have to SuperWord the k-indexed loop - // above in the same loop-opts-phase as the j-indexed loop below, so that they - // have a shared _loop_or_ctrl data structure. - int y = 6; - while (--y > 0) {} - for (long i = 1; i < 6; i++) { - // I suspect that it is the two array references below that are SuperWord-ed, - // and since we do not manage to statically prove they cannot overlap, we add - // a speculative runtime check, i.e. multiversioning in this case. - arrayI[0] += 1; - arrayI[k] = 0; - try { - x = 2 / k % y; - } catch (ArithmeticException a_e) { - } - } - } - long sum = 0; - for (int j = 0; j < arrayB.length; j++) { - // Load below has mem input from Proj below dontinline - // We look up to the mem input (Proj), and down to uses - // that are Stores, checking in_bb on them, which calls - // get_ctrl on that StoreN from the other loop above. - sum += arrayB[j]; - } - return sum; - } - - public static void main(String[] strArr) { - for (int i = 0; i < 1_000; i++) { - test(); - } - } -} diff --git a/test/hotspot/jtreg/compiler/vectorapi/VectorCompressTest.java b/test/hotspot/jtreg/compiler/vectorapi/VectorCompressTest.java deleted file mode 100644 index 7ab60885ad2f5..0000000000000 --- a/test/hotspot/jtreg/compiler/vectorapi/VectorCompressTest.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package compiler.vectorapi; - -import compiler.lib.generators.*; -import compiler.lib.ir_framework.*; -import jdk.incubator.vector.*; -import jdk.test.lib.Asserts; - -/** - * @test - * @bug 8366333 - * @key randomness - * @library /test/lib / - * @summary IR test for VectorAPI compress - * @modules jdk.incubator.vector - * - * @run driver compiler.vectorapi.VectorCompressTest - */ - -public class VectorCompressTest { - static final VectorSpecies B_SPECIES = ByteVector.SPECIES_MAX; - static final VectorSpecies S_SPECIES = ShortVector.SPECIES_MAX; - static final VectorSpecies I_SPECIES = IntVector.SPECIES_MAX; - static final VectorSpecies F_SPECIES = FloatVector.SPECIES_MAX; - static final VectorSpecies L_SPECIES = LongVector.SPECIES_MAX; - static final VectorSpecies D_SPECIES = DoubleVector.SPECIES_MAX; - static final int LENGTH = 512; - static final Generators RD = Generators.G; - static byte[] ba, bb; - static short[] sa, sb; - static int[] ia, ib; - static long[] la, lb; - static float[] fa, fb; - static double[] da, db; - static boolean[] ma; - - static { - ba = new byte[LENGTH]; - bb = new byte[LENGTH]; - sa = new short[LENGTH]; - sb = new short[LENGTH]; - ia = new int[LENGTH]; - ib = new int[LENGTH]; - la = new long[LENGTH]; - lb = new long[LENGTH]; - fa = new float[LENGTH]; - fb = new float[LENGTH]; - da = new double[LENGTH]; - db = new double[LENGTH]; - ma = new boolean[LENGTH]; - - Generator iGen = RD.ints(); - Generator lGen = RD.longs(); - Generator fGen = RD.floats(); - Generator dGen = RD.doubles(); - - for (int i = 0; i < LENGTH; i++) { - ba[i] = iGen.next().byteValue(); - sa[i] = iGen.next().shortValue(); - ma[i] = iGen.next() % 2 == 0; - } - RD.fill(iGen, ia); - RD.fill(lGen, la); - RD.fill(fGen, fa); - RD.fill(dGen, da); - } - - @DontInline - static void verifyVectorCompressByte(int vlen) { - int index = 0; - for (int i = 0; i < vlen; i++) { - if (ma[i]) { - Asserts.assertEquals(ba[i], bb[index++]); - } - } - for (int i = index; i < vlen; i++) { - Asserts.assertEquals((byte)0, bb[i]); - } - } - - @DontInline - static void verifyVectorCompressShort(int vlen) { - int index = 0; - for (int i = 0; i < vlen; i++) { - if (ma[i]) { - Asserts.assertEquals(sa[i], sb[index++]); - } - } - for (int i = index; i < vlen; i++) { - Asserts.assertEquals((short)0, sb[i]); - } - } - - @DontInline - static void verifyVectorCompressInteger(int vlen) { - int index = 0; - for (int i = 0; i < vlen; i++) { - if (ma[i]) { - Asserts.assertEquals(ia[i], ib[index++]); - } - } - for (int i = index; i < vlen; i++) { - Asserts.assertEquals(0, ib[i]); - } - } - - @DontInline - static void verifyVectorCompressLong(int vlen) { - int index = 0; - for (int i = 0; i < vlen; i++) { - if (ma[i]) { - Asserts.assertEquals(la[i], lb[index++]); - } - } - for (int i = index; i < vlen; i++) { - Asserts.assertEquals(0L, lb[i]); - } - } - - @DontInline - static void verifyVectorCompressFloat(int vlen) { - int index = 0; - for (int i = 0; i < vlen; i++) { - if (ma[i]) { - Asserts.assertEquals(fa[i], fb[index++]); - } - } - for (int i = index; i < vlen; i++) { - Asserts.assertEquals(0.0f, fb[i]); - } - } - - @DontInline - static void verifyVectorCompressDouble(int vlen) { - int index = 0; - for (int i = 0; i < vlen; i++) { - if (ma[i]) { - Asserts.assertEquals(da[i], db[index++]); - } - } - for (int i = index; i < vlen; i++) { - Asserts.assertEquals(0.0, db[i]); - } - } - - @Test - @IR(counts = { IRNode.COMPRESS_VB, "= 1" }, - applyIfCPUFeature = { "sve", "true" }) - @IR(counts = { IRNode.COMPRESS_VB, "= 1" }, - applyIfCPUFeatureAnd = {"avx512_vbmi2", "true", "avx512vl", "true"}) - public static void testVectorCompressByte() { - ByteVector av = ByteVector.fromArray(B_SPECIES, ba, 0); - VectorMask m = VectorMask.fromArray(B_SPECIES, ma, 0); - av.compress(m).intoArray(bb, 0); - verifyVectorCompressByte(B_SPECIES.length()); - } - - @Test - @IR(counts = { IRNode.COMPRESS_VS, "= 1" }, - applyIfCPUFeature = { "sve", "true" }) - @IR(counts = { IRNode.COMPRESS_VS, "= 1" }, - applyIfCPUFeatureAnd = {"avx512_vbmi2", "true", "avx512vl", "true"}) - public static void testVectorCompressShort() { - ShortVector av = ShortVector.fromArray(S_SPECIES, sa, 0); - VectorMask m = VectorMask.fromArray(S_SPECIES, ma, 0); - av.compress(m).intoArray(sb, 0); - verifyVectorCompressShort(S_SPECIES.length()); - } - - @Test - @IR(counts = { IRNode.COMPRESS_VI, "= 1" }, - applyIfCPUFeature = { "sve", "true" }) - @IR(counts = { IRNode.COMPRESS_VI, "= 1" }, - applyIfCPUFeatureAnd = {"avx512f", "true", "avx512vl", "true"}) - public static void testVectorCompressInt() { - IntVector av = IntVector.fromArray(I_SPECIES, ia, 0); - VectorMask m = VectorMask.fromArray(I_SPECIES, ma, 0); - av.compress(m).intoArray(ib, 0); - verifyVectorCompressInteger(I_SPECIES.length()); - } - - @Test - @IR(counts = { IRNode.COMPRESS_VL, "= 1" }, - applyIfCPUFeature = { "sve", "true" }) - @IR(counts = { IRNode.COMPRESS_VL, "= 1" }, - applyIfCPUFeatureAnd = {"avx512f", "true", "avx512vl", "true"}) - public static void testVectorCompressLong() { - LongVector av = LongVector.fromArray(L_SPECIES, la, 0); - VectorMask m = VectorMask.fromArray(L_SPECIES, ma, 0); - av.compress(m).intoArray(lb, 0); - verifyVectorCompressLong(L_SPECIES.length()); - } - - @Test - @IR(counts = { IRNode.COMPRESS_VF, "= 1" }, - applyIfCPUFeature = { "sve", "true" }) - @IR(counts = { IRNode.COMPRESS_VF, "= 1" }, - applyIfCPUFeatureAnd = {"avx512f", "true", "avx512vl", "true"}) - public static void testVectorCompressFloat() { - FloatVector av = FloatVector.fromArray(F_SPECIES, fa, 0); - VectorMask m = VectorMask.fromArray(F_SPECIES, ma, 0); - av.compress(m).intoArray(fb, 0); - verifyVectorCompressFloat(F_SPECIES.length()); - } - - @Test - @IR(counts = { IRNode.COMPRESS_VD, "= 1" }, - applyIfCPUFeature = { "sve", "true" }) - @IR(counts = { IRNode.COMPRESS_VD, "= 1" }, - applyIfCPUFeatureAnd = {"avx512f", "true", "avx512vl", "true"}) - public static void testVectorCompressDouble() { - DoubleVector av = DoubleVector.fromArray(D_SPECIES, da, 0); - VectorMask m = VectorMask.fromArray(D_SPECIES, ma, 0); - av.compress(m).intoArray(db, 0); - verifyVectorCompressDouble(D_SPECIES.length()); - } - - public static void main(String[] args) { - TestFramework testFramework = new TestFramework(); - testFramework.setDefaultWarmup(10000) - .addFlags("--add-modules=jdk.incubator.vector") - .start(); - } -} diff --git a/test/hotspot/jtreg/compiler/vectorapi/VectorMaskCompareNotTest.java b/test/hotspot/jtreg/compiler/vectorapi/VectorMaskCompareNotTest.java index 09185f63c6942..235093cceed05 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/VectorMaskCompareNotTest.java +++ b/test/hotspot/jtreg/compiler/vectorapi/VectorMaskCompareNotTest.java @@ -35,7 +35,7 @@ * @library /test/lib / * @summary test combining vector not operation with compare * @modules jdk.incubator.vector - * @requires vm.opt.final.MaxVectorSize == "null" | vm.opt.final.MaxVectorSize >= 16 + * @requires (os.arch != "riscv64" | (os.arch == "riscv64" & vm.cpu.features ~= ".*rvv.*")) * * @run driver compiler.vectorapi.VectorMaskCompareNotTest */ diff --git a/test/hotspot/jtreg/compiler/vectorization/TestSubwordTruncation.java b/test/hotspot/jtreg/compiler/vectorization/TestSubwordTruncation.java index 26a49aba7bf42..2256fd90e3507 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestSubwordTruncation.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestSubwordTruncation.java @@ -29,7 +29,7 @@ /* * @test - * @bug 8350177 8362171 8369881 + * @bug 8350177 8362171 * @summary Ensure that truncation of subword vectors produces correct results * @library /test/lib / * @run driver compiler.vectorization.TestSubwordTruncation @@ -351,57 +351,6 @@ public void checkTestByteReverse(Object[] vals) { } } - @Test - @IR(counts = { IRNode.STORE_VECTOR, "=0" }) - @Arguments(setup = "setupByteArray") - public Object[] testByteReverseBytesS(byte[] in) { - byte[] res = new byte[SIZE]; - for (int i = 0; i < SIZE; i++) { - res[i] = (byte)Short.reverseBytes(in[i]); - } - - return new Object[] { in, res }; - } - - @Check(test = "testByteReverseBytesS") - public void checkTestByteReverseBytesS(Object[] vals) { - byte[] in = (byte[]) vals[0]; - byte[] res = (byte[]) vals[1]; - - for (int i = 0; i < SIZE; i++) { - byte val = (byte)Short.reverseBytes(in[i]); - if (res[i] != val) { - throw new IllegalStateException("Expected " + val + " but got " + res[i] + " for " + in[i]); - } - } - } - - @Test - @IR(counts = { IRNode.STORE_VECTOR, "=0" }) - @Arguments(setup = "setupByteArray") - public Object[] testByteReverseBytesUS(byte[] in) { - byte[] res = new byte[SIZE]; - for (int i = 0; i < SIZE; i++) { - res[i] = (byte)Character.reverseBytes((char)in[i]); - } - - return new Object[] { in, res }; - } - - @Check(test = "testByteReverseBytesUS") - public void checkTestByteReverseBytesUS(Object[] vals) { - byte[] in = (byte[]) vals[0]; - byte[] res = (byte[]) vals[1]; - - for (int i = 0; i < SIZE; i++) { - byte val = (byte)Character.reverseBytes((char)in[i]); - if (res[i] != val) { - throw new IllegalStateException("Expected " + val + " but got " + res[i] + " for " + in[i]); - } - } - } - - @Test @IR(counts = { IRNode.STORE_VECTOR, "=0" }) @Arguments(setup = "setupByteArray") diff --git a/test/hotspot/jtreg/gc/arguments/TestNewSizeThreadIncrease.java b/test/hotspot/jtreg/gc/arguments/TestNewSizeThreadIncrease.java index f885ef7e4620d..efe703f9295c7 100644 --- a/test/hotspot/jtreg/gc/arguments/TestNewSizeThreadIncrease.java +++ b/test/hotspot/jtreg/gc/arguments/TestNewSizeThreadIncrease.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,6 @@ * @library /test/lib * @library / * @requires vm.gc.Serial - * @requires test.thread.factory == null * @modules java.base/jdk.internal.misc * java.management * @run driver gc.arguments.TestNewSizeThreadIncrease diff --git a/test/hotspot/jtreg/gc/g1/TestSkipRebuildRemsetPhase.java b/test/hotspot/jtreg/gc/g1/TestSkipRebuildRemsetPhase.java index 28524869edb39..d973e897fe18e 100644 --- a/test/hotspot/jtreg/gc/g1/TestSkipRebuildRemsetPhase.java +++ b/test/hotspot/jtreg/gc/g1/TestSkipRebuildRemsetPhase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,6 @@ * Fill up a region to above the set G1MixedGCLiveThresholdPercent. * @requires vm.gc.G1 * @library /test/lib - * @requires test.thread.factory == null * @build jdk.test.whitebox.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run driver gc.g1.TestSkipRebuildRemsetPhase diff --git a/test/hotspot/jtreg/runtime/ErrorHandling/AsanReportTest.java b/test/hotspot/jtreg/runtime/ErrorHandling/AsanReportTest.java deleted file mode 100644 index 211df563e6ce5..0000000000000 --- a/test/hotspot/jtreg/runtime/ErrorHandling/AsanReportTest.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2025, IBM Corporation. All rights reserved. - * 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 - * @summary Test that we get ASAN-reports and hs-err files on ASAN error - * @library /test/lib - * @requires vm.asan - * @requires vm.flagless - * @requires vm.debug == true & os.family == "linux" - * @modules java.base/jdk.internal.misc - * java.management - * @run driver AsanReportTest - */ - -// Note: this test can only run on debug since it relies on VMError::controlled_crash() which -// only exists in debug builds. -import java.io.File; -import java.util.regex.Pattern; - -import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.process.ProcessTools; - -public class AsanReportTest { - - private static void do_test() throws Exception { - - ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( - "-Xmx64M", "-XX:CompressedClassSpaceSize=64M", - // Default ASAN options should prevent core file generation, which should overrule +CreateCoredumpOnCrash. - // We test below. - "-XX:+CreateCoredumpOnCrash", - "-Xlog:asan", - // Switch off NMT since it can alter the error ASAN sees; we want the pure double free error - "-XX:NativeMemoryTracking=off", - // Causes double-free in controlled_crash - "-XX:ErrorHandlerTest=18", - "-version"); - - OutputAnalyzer output = new OutputAnalyzer(pb.start()); - - output.shouldNotHaveExitValue(0); - - // ASAN error should appear on stderr - output.shouldContain("CreateCoredumpOnCrash overruled"); - output.shouldContain("JVM caught ASAN Error"); - output.shouldMatch("AddressSanitizer.*double-free"); - output.shouldMatch("# +A fatal error has been detected by the Java Runtime Environment"); - output.shouldMatch("# +fatal error: ASAN"); - output.shouldNotContain("Aborted (core dumped)"); - - File hs_err_file = HsErrFileUtils.openHsErrFileFromOutput(output); - Pattern[] pat = new Pattern[] { - Pattern.compile(".*A S A N.*"), - Pattern.compile(".*AddressSanitizer.*double-free.*"), - Pattern.compile(".*(crash_with_segfault|controlled_crash).*") - }; - HsErrFileUtils.checkHsErrFileContent(hs_err_file, pat, false); - } - - public static void main(String[] args) throws Exception { - do_test(); - } - -} - diff --git a/test/hotspot/jtreg/runtime/ErrorHandling/MachCodeFramesInErrorFile.java b/test/hotspot/jtreg/runtime/ErrorHandling/MachCodeFramesInErrorFile.java index 74cedae5f1a66..5717a576e6542 100644 --- a/test/hotspot/jtreg/runtime/ErrorHandling/MachCodeFramesInErrorFile.java +++ b/test/hotspot/jtreg/runtime/ErrorHandling/MachCodeFramesInErrorFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,6 @@ * @bug 8272586 * @requires vm.flagless * @requires vm.compiler2.enabled - * @requires test.thread.factory == null * @summary Test that abstract machine code is dumped for the top frames in a hs-err log * @library /test/lib * @modules java.base/jdk.internal.misc diff --git a/test/hotspot/jtreg/runtime/MirrorFrame/Asmator.java b/test/hotspot/jtreg/runtime/MirrorFrame/Asmator.java index d8165d8019652..c5d9a4cb59540 100644 --- a/test/hotspot/jtreg/runtime/MirrorFrame/Asmator.java +++ b/test/hotspot/jtreg/runtime/MirrorFrame/Asmator.java @@ -21,28 +21,35 @@ * questions. */ -import java.lang.classfile.ClassFile; -import java.lang.classfile.ClassTransform; -import java.lang.classfile.CodeBuilder; -import java.lang.classfile.CodeElement; -import java.lang.classfile.CodeTransform; +import org.objectweb.asm.*; class Asmator { - static byte[] fixup(byte[] buf) { - return ClassFile.of().transformClass(ClassFile.of().parse(buf), ClassTransform.transformingMethodBodies( - m -> m.methodName().equalsString("callme"), - new CodeTransform() { - @Override - public void atStart(CodeBuilder builder) { - // make receiver go dead! - builder.aconst_null().astore(0); - } - - @Override - public void accept(CodeBuilder builder, CodeElement element) { - builder.with(element); // pass through - } + static byte[] fixup(byte[] buf) throws java.io.IOException { + ClassReader cr = new ClassReader(buf); + ClassWriter cw = new ClassWriter(0); + ClassVisitor cv = new ClassVisitor(Opcodes.ASM4, cw) { + public MethodVisitor visitMethod( + final int access, + final String name, + final String desc, + final String signature, + final String[] exceptions) + { + MethodVisitor mv = super.visitMethod(access, + name, + desc, + signature, + exceptions); + if (mv == null) return null; + if (name.equals("callme")) { + // make receiver go dead! + mv.visitInsn(Opcodes.ACONST_NULL); + mv.visitVarInsn(Opcodes.ASTORE, 0); } - )); + return mv; + } + }; + cr.accept(cv, 0); + return cw.toByteArray(); } } diff --git a/test/hotspot/jtreg/runtime/MirrorFrame/Test8003720.java b/test/hotspot/jtreg/runtime/MirrorFrame/Test8003720.java index 5bcae8e45d1b4..43c8fefacd226 100644 --- a/test/hotspot/jtreg/runtime/MirrorFrame/Test8003720.java +++ b/test/hotspot/jtreg/runtime/MirrorFrame/Test8003720.java @@ -25,6 +25,7 @@ * @test * @bug 8003720 * @summary Method in interpreter stack frame can be deallocated + * @library /testlibrary/asm * @modules java.base/jdk.internal.misc * @compile -XDignore.symbol.file Victim.java * @run main/othervm -Xverify:all -Xint Test8003720 diff --git a/test/hotspot/jtreg/runtime/Monitor/MonitorWithDeadObjectTest.java b/test/hotspot/jtreg/runtime/Monitor/MonitorWithDeadObjectTest.java index b1e6d0aa8c7da..7f9b44a4a76ba 100644 --- a/test/hotspot/jtreg/runtime/Monitor/MonitorWithDeadObjectTest.java +++ b/test/hotspot/jtreg/runtime/Monitor/MonitorWithDeadObjectTest.java @@ -39,8 +39,7 @@ /* * @test id=DumpThreadsBeforeDetach - * @comment Temporarily exclude on Musl-C debug until JDK-8366133 is fixed. - * @requires os.family != "windows" & os.family != "aix" & (!vm.musl | !vm.debug) + * @requires os.family != "windows" & os.family != "aix" * @run main/othervm/native MonitorWithDeadObjectTest 1 */ diff --git a/test/hotspot/jtreg/runtime/NMT/NMTPrintMallocSiteOfCorruptedMemory.java b/test/hotspot/jtreg/runtime/NMT/NMTPrintMallocSiteOfCorruptedMemory.java deleted file mode 100644 index 106295960fd0c..0000000000000 --- a/test/hotspot/jtreg/runtime/NMT/NMTPrintMallocSiteOfCorruptedMemory.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * 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 - * @summary Check the allocation-site stack trace of a corrupted memory at free() time - * @modules java.base/jdk.internal.misc - * @library /test/lib - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail NMTPrintMallocSiteOfCorruptedMemory - */ - -import jdk.test.lib.Utils; -import jdk.test.lib.process.ProcessTools; -import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.whitebox.WhiteBox; - -public class NMTPrintMallocSiteOfCorruptedMemory { - private static final String HEADER_ARG = "header"; - private static final String FOOTER_ARG = "footer"; - private static final String HEADER_AND_SITE_ARG = "header-and-site"; - private static final String FOOTER_AND_SITE_ARG = "footer-and-site"; - private static final int MALLOC_SIZE = 10; - private static WhiteBox wb = WhiteBox.getWhiteBox(); - - static { - System.loadLibrary("MallocHeaderModifier"); - } - - public static native byte modifyHeaderCanary(long malloc_memory); - public static native byte modifyFooterCanary(long malloc_memory, long size); - public static native byte modifyHeaderCanaryAndSiteMarker(long malloc_memory); - public static native byte modifyFooterCanaryAndSiteMarker(long malloc_memory, long size); - - private static void runThisTestWith(String arg) throws Exception { - ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder(new String[] {"-Xbootclasspath/a:.", - "-XX:+UnlockDiagnosticVMOptions", - "-XX:+WhiteBoxAPI", - "-XX:NativeMemoryTracking=detail", - "-Djava.library.path=" + Utils.TEST_NATIVE_PATH, - "NMTPrintMallocSiteOfCorruptedMemory", - arg}); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); - output.shouldMatch("NMT Block at .*, corruption at: "); - switch(arg) { - case HEADER_AND_SITE_ARG, FOOTER_AND_SITE_ARG -> output.shouldContain("allocation-site cannot be shown since the marker is also corrupted."); - case HEADER_ARG, FOOTER_ARG -> { - output.shouldContain("allocated from:"); - output.shouldMatch("\\[.*\\]WB_NMTMalloc\\+0x.*"); - } - } - } - - private static void testModifyHeaderCanary() { - long addr = wb.NMTMalloc(MALLOC_SIZE); - modifyHeaderCanary(addr); - wb.NMTFree(addr); - } - - private static void testModifyFooterCanary() { - long addr = wb.NMTMalloc(MALLOC_SIZE); - modifyFooterCanary(addr, MALLOC_SIZE); - wb.NMTFree(addr); - } - - private static void testModifyHeaderCanaryAndSiteMarker() { - long addr = wb.NMTMalloc(MALLOC_SIZE); - modifyHeaderCanaryAndSiteMarker(addr); - wb.NMTFree(addr); - } - - private static void testModifyFooterCanaryAndSiteMarker() { - long addr = wb.NMTMalloc(MALLOC_SIZE); - modifyFooterCanaryAndSiteMarker(addr, MALLOC_SIZE); - wb.NMTFree(addr); - } - - public static void main(String args[]) throws Exception { - if (args != null && args.length == 1) { - switch (args[0]) { - case HEADER_ARG -> testModifyHeaderCanary(); - case FOOTER_ARG -> testModifyFooterCanary(); - case HEADER_AND_SITE_ARG -> testModifyHeaderCanaryAndSiteMarker(); - case FOOTER_AND_SITE_ARG -> testModifyFooterCanaryAndSiteMarker(); - default -> throw new RuntimeException("Invalid argument for NMTPrintMallocSiteOfCorruptedMemory (" + args[0] + ")"); - } - } else { - runThisTestWith(HEADER_ARG); - runThisTestWith(FOOTER_ARG); - runThisTestWith(HEADER_AND_SITE_ARG); - runThisTestWith(FOOTER_AND_SITE_ARG); - } - } -} diff --git a/test/hotspot/jtreg/runtime/NMT/libMallocHeaderModifier.c b/test/hotspot/jtreg/runtime/NMT/libMallocHeaderModifier.c deleted file mode 100644 index ca51b7212ddc8..0000000000000 --- a/test/hotspot/jtreg/runtime/NMT/libMallocHeaderModifier.c +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include "jni.h" -#include -#include - -JNIEXPORT jint JNICALL -Java_NMTPrintMallocSiteOfCorruptedMemory_modifyHeaderCanary(JNIEnv *env, jclass cls, jlong addr) { - *((jint*)(uintptr_t)addr - 1) = 0; - return 0; -} - -JNIEXPORT jint JNICALL -Java_NMTPrintMallocSiteOfCorruptedMemory_modifyFooterCanary(JNIEnv *env, jclass cls, jlong addr, jint size) { - *((jbyte*)(uintptr_t)addr + size + 1) = 0; - return 0; -} -JNIEXPORT jint JNICALL -Java_NMTPrintMallocSiteOfCorruptedMemory_modifyHeaderCanaryAndSiteMarker(JNIEnv *env, jclass cls, jlong addr) { - jbyte* p = (jbyte*)(uintptr_t)addr - 16; - memset(p, 0xFF , 16); - return 0; -} - -JNIEXPORT jint JNICALL -Java_NMTPrintMallocSiteOfCorruptedMemory_modifyFooterCanaryAndSiteMarker(JNIEnv *env, jclass cls, jlong addr, jint size) { - jbyte* p = (jbyte*)(uintptr_t)addr - 16; - memset(p, 0xFF , 16); - *((jbyte*)(uintptr_t)addr + size + 1) = 0; - return 0; -} diff --git a/test/hotspot/jtreg/runtime/Thread/AsyncExceptionOnMonitorEnter.java b/test/hotspot/jtreg/runtime/Thread/AsyncExceptionOnMonitorEnter.java index a4aa0fe379771..8446ffb20fe2f 100644 --- a/test/hotspot/jtreg/runtime/Thread/AsyncExceptionOnMonitorEnter.java +++ b/test/hotspot/jtreg/runtime/Thread/AsyncExceptionOnMonitorEnter.java @@ -25,7 +25,6 @@ * @test * @bug 8283044 * @summary Stress delivery of asynchronous exceptions while target is at monitorenter - * @requires test.thread.factory == null * @library /test/hotspot/jtreg/testlibrary * @run main/othervm/native AsyncExceptionOnMonitorEnter 0 * @run main/othervm/native -agentlib:AsyncExceptionOnMonitorEnter AsyncExceptionOnMonitorEnter 1 diff --git a/test/hotspot/jtreg/runtime/Thread/StopAtExit.java b/test/hotspot/jtreg/runtime/Thread/StopAtExit.java index 68523c2c189e6..3ceb955609bf3 100644 --- a/test/hotspot/jtreg/runtime/Thread/StopAtExit.java +++ b/test/hotspot/jtreg/runtime/Thread/StopAtExit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 8167108 8266130 8283467 8284632 8286830 * @summary Stress test JVM/TI StopThread() at thread exit. - * @requires test.thread.factory == null * @requires vm.jvmti * @run main/othervm/native -agentlib:StopAtExit StopAtExit */ diff --git a/test/hotspot/jtreg/runtime/cds/AOTMapReader.java b/test/hotspot/jtreg/runtime/cds/CDSMapReader.java similarity index 81% rename from test/hotspot/jtreg/runtime/cds/AOTMapReader.java rename to test/hotspot/jtreg/runtime/cds/CDSMapReader.java index e407d4e2ecce4..f25455b2f0344 100644 --- a/test/hotspot/jtreg/runtime/cds/AOTMapReader.java +++ b/test/hotspot/jtreg/runtime/cds/CDSMapReader.java @@ -26,7 +26,6 @@ import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -34,7 +33,7 @@ This is a simple parser for parsing the output of - java -Xshare:dump -Xlog:aot+map=debug,aot+map+oops=trace:file=aot.map:none:filesize=0 + java -Xshare:dump -Xlog:aot+map=debug,aot+map+oops=trace:file=cds.map:none:filesize=0 The map file contains patterns like this for the heap objects: @@ -60,9 +59,8 @@ */ -public class AOTMapReader { +public class CDSMapReader { public static class MapFile { - HashSet classes = new HashSet<>(); ArrayList heapObjects = new ArrayList<>(); HashMap oopToObject = new HashMap<>(); HashMap narrowOopToObject = new HashMap<>(); @@ -82,20 +80,6 @@ void add(HeapObject heapObject) { public int heapObjectCount() { return heapObjects.size(); } - - void addClass(String className) { - classes.add(className); - } - - public boolean hasClass(String className) { - return classes.contains(className); - } - - public void shouldHaveClass(String className) { - if (!hasClass(className)) { - throw new RuntimeException("AOT map file is missing class " + className); - } - } } public static class HeapAddress { @@ -156,17 +140,13 @@ public static class Field { this.name = name; this.offset = Integer.parseInt(offset); this.referentAddress = new HeapAddress(oopStr, narrowOopStr); - this.lineCount = AOTMapReader.lineCount; + this.lineCount = CDSMapReader.lineCount; } } // 0x00000007ffc00000: 4a5b8701 00000063 00010290 00000000 00010100 fff80003 static Pattern rawDataPattern = Pattern.compile("^0x([0-9a-f]+): *( [0-9a-f]+)+ *$"); - // ------------------------------------------------------------------------------- - // Patterns for heap objects - // ------------------------------------------------------------------------------- - // (one address) // 0x00000007ffc00000: @@ Object java.lang.String static Pattern objPattern1 = Pattern.compile("^0x([0-9a-f]+): @@ Object ([^ ]*)"); @@ -199,15 +179,6 @@ public static class Field { // - injected 'module_entry' 'J' @16 0 (0x0000000000000000) static Pattern moduleEntryPattern = Pattern.compile("- injected 'module_entry' 'J' @[0-9]+[ ]+([0-9]+)"); - // ------------------------------------------------------------------------------- - // Patterns for metaspace objects - // ------------------------------------------------------------------------------- - - // 0x00000008000d1698: @@ Class 512 [Ljdk.internal.vm.FillerElement; - // 0x00000008000d18a0: @@ Class 520 java.lang.Cloneable - static Pattern classPattern = Pattern.compile("^0x([0-9a-f]+): @@ Class [ ]*([0-9]+) (.*)"); - - private static Matcher match(String line, Pattern pattern) { Matcher m = pattern.matcher(line); if (m.find()) { @@ -282,11 +253,6 @@ private static HeapObject parseHeapObjectImpl(String className, String oop, Stri } } - private static void parseClassObject(String className, String addr, String size) throws IOException { - mapFile.addClass(className); - nextLine(); - } - static MapFile mapFile; static BufferedReader reader; static String line = null; // current line being parsed @@ -311,8 +277,6 @@ public static MapFile read(String fileName) { parseHeapObject(m.group(3), m.group(1), m.group(2)); } else if ((m = match(line, objPattern1)) != null) { parseHeapObject(m.group(2), m.group(1), null); - } else if ((m = match(line, classPattern)) != null) { - parseClassObject(m.group(3), m.group(1), m.group(2)); // name, addr, size } else { nextLine(); } @@ -339,15 +303,8 @@ private static void mustContain(HashMap allObjects, Field fiel } } - public static void validate(MapFile mapFile, String classLoadLogFile) throws IOException { - validateOops(mapFile); - if (classLoadLogFile != null) { - validateClasses(mapFile, classLoadLogFile); - } - } - // Check that each oop fields in the HeapObjects must point to a valid HeapObject. - static void validateOops(MapFile mapFile) { + public static void validate(MapFile mapFile) { int count1 = 0; int count2 = 0; for (HeapObject heapObject : mapFile.heapObjects) { @@ -376,10 +333,10 @@ static void validateOops(MapFile mapFile) { if (mapFile.heapObjectCount() > 0) { // heapObjectCount() may be zero if the selected GC doesn't support heap object archiving. if (mapFile.stringCount <= 0) { - throw new RuntimeException("AOT map file should contain at least one string"); + throw new RuntimeException("CDS map file should contain at least one string"); } if (count1 < mapFile.stringCount) { - throw new RuntimeException("AOT map file seems incorrect: " + mapFile.heapObjectCount() + + throw new RuntimeException("CDS map file seems incorrect: " + mapFile.heapObjectCount() + " objects (" + mapFile.stringCount + " strings). Each string should" + " have one non-null oop field but we found only " + count1 + " non-null oop field references"); @@ -387,26 +344,8 @@ static void validateOops(MapFile mapFile) { } } - // classLoadLogFile should be generated with -Xlog:class+load:file=:none:filesize=0 - // Check that every class loaded from "source: shared objects file" have an entry inside the mapFile. - static void validateClasses(MapFile mapFile, String classLoadLogFile) throws IOException { - try (BufferedReader r = new BufferedReader(new FileReader(classLoadLogFile))) { - String line; - String suffix = " source: shared objects file"; - int suffixLen = suffix.length(); - while ((line = r.readLine()) != null) { - if (line.endsWith(suffix)) { - String className = line.substring(0, line.length() - suffixLen); - if (!mapFile.hasClass(className)) { - throw new RuntimeException("AOT map file is missing class " + className); - } - } - } - } - } - - public static void main(String args[]) throws IOException { + public static void main(String args[]) { MapFile mapFile = read(args[0]); - validate(mapFile, null); + validate(mapFile); } } diff --git a/test/hotspot/jtreg/runtime/cds/AOTMapTest.java b/test/hotspot/jtreg/runtime/cds/CDSMapTest.java similarity index 92% rename from test/hotspot/jtreg/runtime/cds/AOTMapTest.java rename to test/hotspot/jtreg/runtime/cds/CDSMapTest.java index dff980908598e..5a9fa82552bea 100644 --- a/test/hotspot/jtreg/runtime/cds/AOTMapTest.java +++ b/test/hotspot/jtreg/runtime/cds/CDSMapTest.java @@ -27,7 +27,7 @@ * @summary Test the contents of -Xlog:aot+map * @requires vm.cds * @library /test/lib - * @run driver/timeout=240 AOTMapTest + * @run driver/timeout=240 CDSMapTest */ import jdk.test.lib.cds.CDSOptions; @@ -37,7 +37,7 @@ import jdk.test.lib.process.ProcessTools; import java.util.ArrayList; -public class AOTMapTest { +public class CDSMapTest { public static void main(String[] args) throws Exception { doTest(false); @@ -79,8 +79,8 @@ static String dump(ArrayList args) throws Exception { .addSuffix(args); CDSTestUtils.createArchiveAndCheck(opts); - AOTMapReader.MapFile mapFile = AOTMapReader.read(mapName); - AOTMapReader.validate(mapFile, null); + CDSMapReader.MapFile mapFile = CDSMapReader.read(mapName); + CDSMapReader.validate(mapFile); return archiveName; } @@ -98,7 +98,7 @@ static void exec(ArrayList vmArgs, String archiveFile) throws Exception OutputAnalyzer out = CDSTestUtils.executeAndLog(pb, "exec"); out.shouldHaveExitValue(0); - AOTMapReader.MapFile mapFile = AOTMapReader.read(mapName); - AOTMapReader.validate(mapFile, null); + CDSMapReader.MapFile mapFile = CDSMapReader.read(mapName); + CDSMapReader.validate(mapFile); } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/AOTMapTest.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/AOTMapTest.java index 6cbfcbbd3c3f9..bcd2c71fea094 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/AOTMapTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/AOTMapTest.java @@ -26,10 +26,9 @@ * @bug 8362566 * @summary Test the contents of -Xlog:aot+map with AOT workflow * @requires vm.cds.supports.aot.class.linking - * @library /test/lib /test/hotspot/jtreg/runtime/cds /test/hotspot/jtreg/runtime/cds/appcds/test-classes - * @build AOTMapTest Hello + * @library /test/lib /test/hotspot/jtreg/runtime/cds + * @build AOTMapTest * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar AOTMapTestApp - * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar cust.jar Hello * @run driver/timeout=240 AOTMapTest AOT --two-step-training */ @@ -38,18 +37,15 @@ * @bug 8362566 * @summary Test the contents of -Xlog:aot+map with dynamic CDS archive * @requires vm.cds.supports.aot.class.linking - * @library /test/lib /test/hotspot/jtreg/runtime/cds /test/hotspot/jtreg/runtime/cds/appcds/test-classes + * @library /test/lib /test/hotspot/jtreg/runtime/cds * @build jdk.test.whitebox.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @build AOTMapTest Hello + * @build AOTMapTest * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar AOTMapTestApp - * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar cust.jar Hello * @run main/othervm/timeout=240 -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. AOTMapTest DYNAMIC */ -import java.io.File; -import java.net.URL; -import java.net.URLClassLoader; + import java.util.ArrayList; import jdk.test.lib.cds.CDSAppTester; import jdk.test.lib.helpers.ClassFileInstaller; @@ -58,7 +54,6 @@ public class AOTMapTest { static final String appJar = ClassFileInstaller.getJarPath("app.jar"); static final String mainClass = "AOTMapTestApp"; - static final String classLoadLogFile = "production.class.load.log"; public static void main(String[] args) throws Exception { doTest(args); @@ -68,25 +63,13 @@ public static void doTest(String[] args) throws Exception { Tester tester = new Tester(); tester.run(args); - if (tester.isDynamicWorkflow()) { - // For dynamic workflow, the AOT map file doesn't include classes in the base archive, so - // AOTMapReader.validateClasses() will fail. - validate(tester.dumpMapFile, false); - } else { - validate(tester.dumpMapFile, true); - } - validate(tester.runMapFile, true); + validate(tester.dumpMapFile); + validate(tester.runMapFile); } - static void validate(String mapFileName, boolean checkClases) throws Exception { - AOTMapReader.MapFile mapFile = AOTMapReader.read(mapFileName); - if (checkClases) { - AOTMapReader.validate(mapFile, classLoadLogFile); - } else { - AOTMapReader.validate(mapFile, null); - } - mapFile.shouldHaveClass("AOTMapTestApp"); // built-in class - mapFile.shouldHaveClass("Hello"); // unregistered class + static void validate(String mapFileName) { + CDSMapReader.MapFile mapFile = CDSMapReader.read(mapFileName); + CDSMapReader.validate(mapFile); } static class Tester extends CDSAppTester { @@ -114,13 +97,12 @@ public String[] vmArgs(RunMode runMode) { // filesize=0 ensures that a large map file not broken up in multiple files. String logMapPrefix = "-Xlog:aot+map=debug,aot+map+oops=trace:file="; - String logSuffix = ":none:filesize=0"; + String logMapSuffix = ":none:filesize=0"; if (runMode == RunMode.ASSEMBLY || runMode == RunMode.DUMP_DYNAMIC) { - vmArgs.add(logMapPrefix + dumpMapFile + logSuffix); + vmArgs.add(logMapPrefix + dumpMapFile + logMapSuffix); } else if (runMode == RunMode.PRODUCTION) { - vmArgs.add(logMapPrefix + runMapFile + logSuffix); - vmArgs.add("-Xlog:class+load:file=" + classLoadLogFile + logSuffix); + vmArgs.add(logMapPrefix + runMapFile + logMapSuffix); } return vmArgs.toArray(new String[vmArgs.size()]); @@ -136,16 +118,7 @@ public String[] appCommandLine(RunMode runMode) { } class AOTMapTestApp { - public static void main(String[] args) throws Exception { + public static void main(String[] args) { System.out.println("Hello AOTMapTestApp"); - testCustomLoader(); - } - - static void testCustomLoader() throws Exception { - File custJar = new File("cust.jar"); - URL[] urls = new URL[] {custJar.toURI().toURL()}; - URLClassLoader loader = new URLClassLoader(urls, AOTMapTestApp.class.getClassLoader()); - Class c = loader.loadClass("Hello"); - System.out.println(c); } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/ResolvedConstants.java b/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/ResolvedConstants.java index 621d6383ff41e..bc2ac9db2abfc 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/ResolvedConstants.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/ResolvedConstants.java @@ -174,9 +174,14 @@ static void checkAssemblyOutput(String args[], OutputAnalyzer out) { // Indy References --- if (aotClassLinking) { testGroup("Indy References", out) + .shouldContain("Cannot aot-resolve Lambda proxy because OldConsumer is excluded") + .shouldContain("Cannot aot-resolve Lambda proxy because OldProvider is excluded") + .shouldContain("Cannot aot-resolve Lambda proxy because OldClass is excluded") .shouldContain("Cannot aot-resolve Lambda proxy of interface type InterfaceWithClinit") .shouldMatch("klasses.* app *NormalClass[$][$]Lambda/.* hidden aot-linked inited") - .shouldMatch("archived indy *CP entry.*StringConcatTest .* => java/lang/invoke/StringConcatFactory.makeConcatWithConstants"); + .shouldNotMatch("klasses.* app *SubOfOldClass[$][$]Lambda/") + .shouldMatch("archived indy *CP entry.*StringConcatTest .* => java/lang/invoke/StringConcatFactory.makeConcatWithConstants") + .shouldNotMatch("archived indy *CP entry.*StringConcatTestOld .* => java/lang/invoke/StringConcatFactory.makeConcatWithConstants"); } } diff --git a/test/hotspot/jtreg/runtime/handshake/HandshakeWalkStackTest.java b/test/hotspot/jtreg/runtime/handshake/HandshakeWalkStackTest.java index 6644d14dbc812..701e1ec6ec1df 100644 --- a/test/hotspot/jtreg/runtime/handshake/HandshakeWalkStackTest.java +++ b/test/hotspot/jtreg/runtime/handshake/HandshakeWalkStackTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, 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 @@ -24,7 +24,6 @@ /* * @test HandshakeWalkStackTest - * @requires test.thread.factory == null * @library /testlibrary /test/lib * @build HandshakeWalkStackTest * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox diff --git a/test/hotspot/jtreg/serviceability/attach/EarlyDynamicLoad/EarlyDynamicLoad.java b/test/hotspot/jtreg/serviceability/attach/EarlyDynamicLoad/EarlyDynamicLoad.java deleted file mode 100644 index cb1596da08cc4..0000000000000 --- a/test/hotspot/jtreg/serviceability/attach/EarlyDynamicLoad/EarlyDynamicLoad.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * 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. - */ - -import com.sun.tools.attach.VirtualMachine; -import com.sun.tools.attach.AgentLoadException; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.AfterAll; - -import java.io.File; -import java.io.InputStream; -import java.io.OutputStream; -import java.util.concurrent.TimeUnit; -import jdk.test.lib.dcmd.PidJcmdExecutor; -import jdk.test.lib.process.OutputAnalyzer; -import jdk.test.lib.process.ProcessTools; -import jdk.test.lib.Utils; - -/* - * @test EarlyDynamicLoad - * @summary Test that dynamic attach fails gracefully when the JVM is not in live phase. - * @requires vm.jvmti - * @library /test/lib - * @run junit EarlyDynamicLoad - */ -public class EarlyDynamicLoad { - private static final String EXPECTED_MESSAGE = "Dynamic agent loading is only permitted in the live phase"; - - private static Process child; - - @BeforeAll - static void startAndWaitChild() throws Exception { - child = ProcessTools.createTestJavaProcessBuilder( - "-XX:+StartAttachListener", - "-agentpath:" + Utils.TEST_NATIVE_PATH + File.separator + System.mapLibraryName("EarlyDynamicLoad"), - "--version").start(); - - // Wait until the process enters VMStartCallback - try (InputStream is = child.getInputStream()) { - is.read(); - } - } - - @AfterAll - static void stopChild() throws Exception { - try (OutputStream os = child.getOutputStream()) { - os.write(0); - } - - if (!child.waitFor(5, TimeUnit.SECONDS)) { - child.destroyForcibly(); - throw new AssertionError("Timed out while waiting child process to complete"); - } - - OutputAnalyzer analyzer = new OutputAnalyzer(child); - analyzer.shouldHaveExitValue(0); - analyzer.stderrShouldBeEmpty(); - } - - @Test - public void virtualMachine() throws Exception { - try { - VirtualMachine vm = VirtualMachine.attach(String.valueOf(child.pid())); - vm.loadAgent("some.jar"); - vm.detach(); - throw new AssertionError("Should have failed with AgentLoadException"); - } catch(AgentLoadException exception) { - if (!exception.getMessage().contains(EXPECTED_MESSAGE)) { - throw new AssertionError("Unexpected error message", exception); - } - } - } - - @Test - public void jcmd() throws Exception { - PidJcmdExecutor executor = new PidJcmdExecutor(String.valueOf(child.pid())); - OutputAnalyzer out = executor.execute("JVMTI.agent_load some.jar"); - - out.shouldHaveExitValue(0); - out.stdoutShouldContain(EXPECTED_MESSAGE); - } -} diff --git a/test/hotspot/jtreg/serviceability/attach/EarlyDynamicLoad/libEarlyDynamicLoad.cpp b/test/hotspot/jtreg/serviceability/attach/EarlyDynamicLoad/libEarlyDynamicLoad.cpp deleted file mode 100644 index 3991926306e4f..0000000000000 --- a/test/hotspot/jtreg/serviceability/attach/EarlyDynamicLoad/libEarlyDynamicLoad.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include -#include -#include - -extern "C" { - -static void JNICALL VMStartCallback(jvmtiEnv* jvmti, JNIEnv* env) { - putchar('1'); - fflush(stdout); - getchar(); -} - -JNIEXPORT int Agent_OnLoad(JavaVM* vm, char* options, void* reserved) { - jvmtiEnv* jvmti; - if (vm->GetEnv((void**) &jvmti, JVMTI_VERSION_1_0) != JVMTI_ERROR_NONE) { - fprintf(stderr, "JVMTI error occurred during GetEnv\n"); - return JNI_ERR; - } - - jvmtiEventCallbacks callbacks; - memset(&callbacks, 0, sizeof(callbacks)); - callbacks.VMStart = VMStartCallback; - - if (jvmti->SetEventCallbacks(&callbacks, sizeof(callbacks)) != JVMTI_ERROR_NONE) { - fprintf(stderr, "JVMTI error occurred during SetEventCallbacks\n"); - return JNI_ERR; - } - if (jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_VM_START, nullptr) != JVMTI_ERROR_NONE) { - fprintf(stderr, "JVMTI error occurred during SetEventNotificationMode\n"); - return JNI_ERR; - } - - return JNI_OK; -} - -} diff --git a/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/MissedStackMapFrames/MissedStackMapFrames.java b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/MissedStackMapFrames/MissedStackMapFrames.java index 941c6e79bb875..534f077eaf485 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/MissedStackMapFrames/MissedStackMapFrames.java +++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/MissedStackMapFrames/MissedStackMapFrames.java @@ -27,15 +27,17 @@ * @bug 8228604 * * @requires vm.jvmti + * @library /testlibrary/asm * @library /test/lib * * @run main/othervm/native -agentlib:MissedStackMapFrames MissedStackMapFrames */ -import java.lang.classfile.Attributes; -import java.lang.classfile.ClassFile; -import java.lang.classfile.ClassModel; -import java.lang.classfile.MethodModel; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; + public class MissedStackMapFrames { static { @@ -56,19 +58,30 @@ public class MissedStackMapFrames { private static native byte[] retransformBytes(int idx); private static int getStackMapFrameCount(byte[] classfileBuffer) { - ClassModel clazz = ClassFile.of().parse(classfileBuffer); - int count = 0; - for (MethodModel method : clazz.methods()) { - var foundStackMapTable = method.code().flatMap(code -> code.findAttribute(Attributes.stackMapTable())); - if (foundStackMapTable.isPresent()) { - int methodFrames = foundStackMapTable.get().entries().size(); - log(" method " + method.methodName() + " - " + methodFrames + " frames"); - count += methodFrames; - } else { - log(" method " + method.methodName() + " - No StackMapTable"); + ClassReader reader = new ClassReader(classfileBuffer); + final int[] frameCount = {0}; + ClassVisitor cv = new ClassVisitor(Opcodes.ASM9) { + @Override + public MethodVisitor visitMethod(int access, String name, + String descriptor, String signature, + String[] exceptions) { + return new MethodVisitor(Opcodes.ASM9) { + private int methodFrames = 0; + @Override + public void visitFrame(int type, int numLocal, Object[] local, + int numStack, Object[] stack) { + methodFrames++; + } + @Override + public void visitEnd() { + log(" method " + name + " - " + methodFrames + " frames"); + frameCount[0] += methodFrames; + } + }; } - } - return count; + }; + reader.accept(cv, 0); + return frameCount[0]; } private static int checkStackMapFrames(String mode, byte[] classfileBuffer) { diff --git a/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineAnnotations.java b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineAnnotations.java index 320531148d464..aad876d7181e9 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineAnnotations.java +++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineAnnotations.java @@ -24,6 +24,7 @@ /* * @test * @library /test/lib + * @library /testlibrary/asm * @summary Test that type annotations are retained after a retransform * @requires vm.jvmti * @modules java.base/jdk.internal.misc @@ -45,11 +46,6 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; -import java.lang.classfile.ClassBuilder; -import java.lang.classfile.ClassElement; -import java.lang.classfile.ClassFile; -import java.lang.classfile.ClassTransform; -import java.lang.classfile.FieldModel; import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.IllegalClassFormatException; import java.lang.instrument.Instrumentation; @@ -59,10 +55,17 @@ import java.lang.reflect.AnnotatedType; import java.lang.reflect.AnnotatedWildcardType; import java.lang.reflect.Executable; +import java.lang.reflect.TypeVariable; import java.security.ProtectionDomain; -import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedList; import java.util.List; import java.util.Map; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.FieldVisitor; +import static org.objectweb.asm.Opcodes.ASM7; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE_USE) @@ -83,27 +86,53 @@ public byte[] asm(ClassLoader loader, String className, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { - // Shuffle constant pool - ClassFile context = ClassFile.of(ClassFile.ConstantPoolSharingOption.NEW_POOL); - return context.transformClass(context.parse(classfileBuffer), new ClassTransform() { - final List dummyFields = new ArrayList<>(); - - @Override - public void accept(ClassBuilder builder, ClassElement element) { - if (element instanceof FieldModel field && field.fieldName().stringValue().startsWith("dummy")) { - // Hold on to the associated constant pool entries too - dummyFields.addLast(field); - } else { - builder.with(element); - } + ClassWriter cw = new ClassWriter(0); + ClassVisitor cv = new ReAddDummyFieldsClassVisitor(ASM7, cw) { }; + ClassReader cr = new ClassReader(classfileBuffer); + cr.accept(cv, 0); + return cw.toByteArray(); + } + + public class ReAddDummyFieldsClassVisitor extends ClassVisitor { + + LinkedList fields = new LinkedList<>(); + + public ReAddDummyFieldsClassVisitor(int api, ClassVisitor cv) { + super(api, cv); + } + + @Override public FieldVisitor visitField(int access, String name, + String desc, String signature, Object value) { + if (name.startsWith("dummy")) { + // Remove dummy field + fields.addLast(new F(access, name, desc, signature, value)); + return null; } + return cv.visitField(access, name, desc, signature, value); + } - @Override - public void atEnd(ClassBuilder builder) { - // Add the associated constant pool entries to the end of the CP - dummyFields.forEach(builder); + @Override public void visitEnd() { + F f; + while ((f = fields.pollFirst()) != null) { + // Re-add dummy fields + cv.visitField(f.access, f.name, f.desc, f.signature, f.value); } - }); + } + + private class F { + private int access; + private String name; + private String desc; + private String signature; + private Object value; + F(int access, String name, String desc, String signature, Object value) { + this.access = access; + this.name = name; + this.desc = desc; + this.signature = signature; + this.value = value; + } + } } @Override public byte[] transform(ClassLoader loader, String className, diff --git a/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineGenericSignatureTest.java b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineGenericSignatureTest.java index 923253e80513c..f220a93f187b9 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineGenericSignatureTest.java +++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineGenericSignatureTest.java @@ -35,11 +35,6 @@ import java.io.File; import java.io.FileOutputStream; -import java.lang.classfile.ClassBuilder; -import java.lang.classfile.ClassElement; -import java.lang.classfile.ClassFile; -import java.lang.classfile.ClassTransform; -import java.lang.classfile.attribute.SourceFileAttribute; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; @@ -146,28 +141,27 @@ private void printDisassembled(String description, Class cls, byte[] bytes) thro private byte[] getNewClassBytes() { byte[] bytecode = InMemoryJavaCompiler.compile(GenericSignatureTarget.class.getName(), newTargetClassSource); - ClassFile context = ClassFile.of(); - return context.transformClass(context.parse(bytecode), new ClassTransform() { + ClassWriter cw = new ClassWriter(0); + ClassReader cr = new ClassReader(bytecode); + cr.accept(new ClassVisitor(Opcodes.ASM7, cw) { private boolean sourceSet = false; @Override - public void accept(ClassBuilder builder, ClassElement element) { - if (element instanceof SourceFileAttribute src) { - sourceSet = true; - log("Changing source: \"" + src.sourceFile() + "\" -> \"" + sourceFileNameNew + "\""); - builder.with(SourceFileAttribute.of(sourceFileNameNew)); - } else { - builder.with(element); - } + public void visitSource(String source, String debug) { + sourceSet = true; + log("Changing source: \"" + source + "\" -> \"" + sourceFileNameNew + "\""); + super.visitSource(sourceFileNameNew, debug); } @Override - public void atEnd(ClassBuilder builder) { + public void visitEnd() { if (!sourceSet) { log("Set source: \"" + sourceFileNameNew + "\""); - builder.with(SourceFileAttribute.of(sourceFileNameNew)); + super.visitSource(sourceFileNameNew, null); } + super.visitEnd(); } - }); + }, 0); + return cw.toByteArray(); } private void runTest() throws Throwable { diff --git a/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineObject.java b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineObject.java index d3349282410f3..de90c15b5a52b 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineObject.java +++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineObject.java @@ -27,6 +27,7 @@ * @summary Ensure Object natives stay registered after redefinition * @requires vm.jvmti * @library /test/lib + * @library /testlibrary/asm * @modules java.base/jdk.internal.misc * java.compiler * java.instrument @@ -40,15 +41,19 @@ import java.io.FileNotFoundException; import java.io.PrintWriter; import java.lang.RuntimeException; -import java.lang.classfile.ClassBuilder; -import java.lang.classfile.ClassElement; -import java.lang.classfile.ClassFile; -import java.lang.classfile.ClassFileVersion; import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.IllegalClassFormatException; import java.lang.instrument.Instrumentation; import java.lang.instrument.UnmodifiableClassException; import java.security.ProtectionDomain; +import java.util.Arrays; + +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; + +import static org.objectweb.asm.Opcodes.ASM6; +import static org.objectweb.asm.Opcodes.V1_8; public class RedefineObject { @@ -64,14 +69,31 @@ public byte[] asm(ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { - return ClassFile.of().transformClass(ClassFile.of().parse(classfileBuffer), (classBuilder, classElement) -> { - if (classElement instanceof ClassFileVersion cfv) { - // Force a redefine with different class file versions - classBuilder.with(ClassFileVersion.of(cfv.majorVersion() - 1, 0)); - } else { - classBuilder.with(classElement); - } - }); + ClassWriter cw = new ClassWriter(0); + // Force an older ASM to force a bytecode update + ClassVisitor cv = new DummyClassVisitor(ASM6, cw) { }; + ClassReader cr = new ClassReader(classfileBuffer); + cr.accept(cv, 0); + byte[] bytes = cw.toByteArray(); + return bytes; + } + + public class DummyClassVisitor extends ClassVisitor { + + public DummyClassVisitor(int api, ClassVisitor cv) { + super(api, cv); + } + + public void visit( + final int version, + final int access, + final String name, + final String signature, + final String superName, + final String[] interfaces) { + // Artificially lower to JDK 8 version to force a redefine + cv.visit(V1_8, access, name, signature, superName, interfaces); + } } @Override public byte[] transform(ClassLoader loader, String className, diff --git a/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineRetransform/RedefineRetransform.java b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineRetransform/RedefineRetransform.java index 167b546ac9d29..a09d1dc318e75 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineRetransform/RedefineRetransform.java +++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineRetransform/RedefineRetransform.java @@ -27,6 +27,7 @@ * @bug 7124710 * * @requires vm.jvmti + * @library /testlibrary/asm * @library /test/lib * * @comment main/othervm/native -Xlog:redefine*=trace -agentlib:RedefineRetransform RedefineRetransform @@ -41,17 +42,13 @@ import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; -import java.lang.classfile.Annotation; -import java.lang.classfile.AnnotationElement; -import java.lang.classfile.AnnotationValue; -import java.lang.classfile.Attributes; -import java.lang.classfile.ClassFile; -import java.lang.classfile.ClassModel; -import java.lang.classfile.ClassTransform; -import java.lang.classfile.attribute.RuntimeVisibleAnnotationsAttribute; -import java.lang.constant.ClassDesc; -import java.util.List; -import java.util.NoSuchElementException; + +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Opcodes; +import org.objectweb.asm.Type; /* * The test verifies that after interleaved RedefineClasses/RetransformClasses calls @@ -84,32 +81,67 @@ public TestClass() { } // Class bytes for initial TestClass (ClassVersion == 0). private static byte[] initialClassBytes; - private static final ClassDesc CD_ClassVersion = ClassVersion.class.describeConstable().orElseThrow(); + private static class VersionScanner extends ClassVisitor { + private Integer detectedVersion; + private Integer versionToSet; + // to get version + public VersionScanner() { + super(Opcodes.ASM7); + } + // to set version + public VersionScanner(int verToSet, ClassVisitor classVisitor) { + super(Opcodes.ASM7, classVisitor); + versionToSet = verToSet; + } + + public int detectedVersion() { + if (detectedVersion == null) { + throw new RuntimeException("Version not detected"); + } + return detectedVersion; + } + + @Override + public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) { + //log("visitAnnotation: descr = '" + descriptor + "', visible = " + visible); + if (Type.getDescriptor(ClassVersion.class).equals(descriptor)) { + return new AnnotationVisitor(Opcodes.ASM7, super.visitAnnotation(descriptor, visible)) { + @Override + public void visit(String name, Object value) { + //log("visit: name = '" + name + "', value = " + value + // + " (" + (value == null ? "N/A" : value.getClass()) + ")"); + if ("value".equals(name) && value instanceof Integer intValue) { + detectedVersion = intValue; + if (versionToSet != null) { + //log("replace with " + versionToSet); + value = versionToSet; + } + } + super.visit(name, value); + } + }; + } + return super.visitAnnotation(descriptor, visible); + } + } // Generates TestClass class bytes with the specified ClassVersion value. private static byte[] getClassBytes(int ver) { if (ver < 0) { return null; } - return ClassFile.of().transformClass(ClassFile.of().parse(initialClassBytes), - // overwrites previously passed RVAA - ClassTransform.endHandler(classBuilder -> classBuilder.with(RuntimeVisibleAnnotationsAttribute - .of(Annotation.of(CD_ClassVersion, AnnotationElement.ofInt("value", ver)))))); + ClassWriter cw = new ClassWriter(0); + ClassReader cr = new ClassReader(initialClassBytes); + cr.accept(new VersionScanner(ver, cw), 0); + return cw.toByteArray(); } // Extracts ClassVersion values from the provided class bytes. private static int getClassBytesVersion(byte[] classBytes) { - ClassModel classModel = ClassFile.of().parse(classBytes); - RuntimeVisibleAnnotationsAttribute rvaa = classModel.findAttribute(Attributes.runtimeVisibleAnnotations()).orElseThrow(); - List classVersionElementValuePairs = rvaa.annotations().stream() - .filter(anno -> anno.className().isFieldType(CD_ClassVersion)) - .findFirst().orElseThrow().elements(); - if (classVersionElementValuePairs.size() != 1) - throw new NoSuchElementException(); - AnnotationElement elementValuePair = classVersionElementValuePairs.getFirst(); - if (!elementValuePair.name().equalsString("value") || !(elementValuePair.value() instanceof AnnotationValue.OfInt intVal)) - throw new NoSuchElementException(); - return intVal.intValue(); + ClassReader cr = new ClassReader(classBytes); + VersionScanner scanner = new VersionScanner(); + cr.accept(scanner, 0); + return scanner.detectedVersion(); } static void init() { diff --git a/test/hotspot/jtreg/serviceability/jvmti/vthread/ThreadStateTest/ThreadStateTest.java b/test/hotspot/jtreg/serviceability/jvmti/vthread/ThreadStateTest/ThreadStateTest.java index c6a7debed1afe..4c8b9bb030f8b 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/vthread/ThreadStateTest/ThreadStateTest.java +++ b/test/hotspot/jtreg/serviceability/jvmti/vthread/ThreadStateTest/ThreadStateTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,17 +27,15 @@ * @summary Exercise JvmtiThreadState creation concurrently with terminating vthreads * @requires vm.continuations * @modules java.base/java.lang:+open - * @library /test/lib * @run main/othervm/native -agentlib:ThreadStateTest ThreadStateTest */ +import java.util.concurrent.*; import java.util.Arrays; import java.util.ArrayList; import java.util.List; -import java.util.concurrent.Executors; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.ThreadFactory; -import jdk.test.lib.thread.VThreadScheduler; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; public class ThreadStateTest { static final int VTHREAD_COUNT = 64; @@ -61,7 +59,7 @@ private void runTest() throws Exception { while (tryCount-- > 0) { ExecutorService scheduler = Executors.newFixedThreadPool(8); - ThreadFactory factory = VThreadScheduler.virtualThreadBuilder(scheduler).factory(); + ThreadFactory factory = virtualThreadBuilder(scheduler).factory(); List virtualThreads = new ArrayList<>(); for (int i = 0; i < VTHREAD_COUNT; i++) { @@ -100,4 +98,22 @@ public static void main(String[] args) throws Exception { ThreadStateTest obj = new ThreadStateTest(); obj.runTest(); } + + private static Thread.Builder.OfVirtual virtualThreadBuilder(Executor scheduler) { + Thread.Builder.OfVirtual builder = Thread.ofVirtual(); + try { + Class clazz = Class.forName("java.lang.ThreadBuilders$VirtualThreadBuilder"); + Constructor ctor = clazz.getDeclaredConstructor(Executor.class); + ctor.setAccessible(true); + return (Thread.Builder.OfVirtual) ctor.newInstance(scheduler); + } catch (InvocationTargetException e) { + Throwable cause = e.getCause(); + if (cause instanceof RuntimeException re) { + throw re; + } + throw new RuntimeException(e); + } catch (Exception e) { + throw new RuntimeException(e); + } + } } diff --git a/test/hotspot/jtreg/serviceability/sa/LingeredAppWithVirtualThread.java b/test/hotspot/jtreg/serviceability/sa/LingeredAppWithVirtualThread.java deleted file mode 100644 index ca98506e13381..0000000000000 --- a/test/hotspot/jtreg/serviceability/sa/LingeredAppWithVirtualThread.java +++ /dev/null @@ -1,87 +0,0 @@ - -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2025, NTT DATA - * 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.lang.invoke.MethodHandle; -import java.lang.foreign.Arena; -import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.Linker; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.SymbolLookup; -import java.lang.foreign.ValueLayout; -import java.util.concurrent.CountDownLatch; - -import jdk.test.lib.apps.LingeredApp; - -public class LingeredAppWithVirtualThread extends LingeredApp implements Runnable { - - private static final String THREAD_NAME = "target thread"; - - private static final MethodHandle hndSleep; - - private static final int sleepArg; - - private static final CountDownLatch signal = new CountDownLatch(1); - - static { - MemorySegment func; - if (System.getProperty("os.name").startsWith("Windows")) { - func = SymbolLookup.libraryLookup("Kernel32", Arena.global()) - .findOrThrow("Sleep"); - sleepArg = 3600_000; // 1h in milliseconds - } else { - func = Linker.nativeLinker() - .defaultLookup() - .findOrThrow("sleep"); - sleepArg = 3600; // 1h in seconds - } - - var desc = FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.JAVA_INT); - hndSleep = Linker.nativeLinker().downcallHandle(func, desc); - } - - @Override - public void run() { - Thread.yield(); - signal.countDown(); - try { - hndSleep.invoke(sleepArg); - } catch (Throwable t) { - throw new RuntimeException(t); - } - } - - public static void main(String[] args) { - try { - Thread.ofVirtual() - .name(THREAD_NAME) - .start(new LingeredAppWithVirtualThread()); - - signal.await(); - LingeredApp.main(args); - } catch (Exception e) { - throw new RuntimeException(e); - } - } -} diff --git a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackWithVirtualThread.java b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackWithVirtualThread.java deleted file mode 100644 index 6d7921c7ed8b4..0000000000000 --- a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackWithVirtualThread.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2025, NTT DATA - * 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.util.ArrayList; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import jdk.test.lib.JDKToolLauncher; -import jdk.test.lib.SA.SATestUtils; -import jdk.test.lib.Utils; -import jdk.test.lib.apps.LingeredApp; -import jdk.test.lib.process.OutputAnalyzer; - -/** - * @test - * @bug 8369505 - * @requires vm.hasSA - * @library /test/lib - * @run driver TestJhsdbJstackWithVirtualThread - */ -public class TestJhsdbJstackWithVirtualThread { - - private static void runJstack(LingeredApp app) throws Exception { - JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jhsdb"); - launcher.addVMArgs(Utils.getFilteredTestJavaOpts("-showversion")); - launcher.addToolArg("jstack"); - launcher.addToolArg("--pid"); - launcher.addToolArg(Long.toString(app.getPid())); - - ProcessBuilder pb = SATestUtils.createProcessBuilder(launcher); - Process jhsdb = pb.start(); - OutputAnalyzer out = new OutputAnalyzer(jhsdb); - - jhsdb.waitFor(); - - System.out.println(out.getStdout()); - System.err.println(out.getStderr()); - - out.stderrShouldBeEmptyIgnoreDeprecatedWarnings(); - out.shouldNotContain("must have non-zero frame size"); - } - - public static void main(String... args) throws Exception { - SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work. - LingeredApp app = null; - - try { - app = new LingeredAppWithVirtualThread(); - LingeredApp.startApp(app); - System.out.println("Started LingeredApp with pid " + app.getPid()); - runJstack(app); - System.out.println("Test Completed"); - } catch (Throwable e) { - e.printStackTrace(); - throw e; - } finally { - LingeredApp.stopApp(app); - } - } -} diff --git a/test/hotspot/jtreg/testlibrary_tests/generators/tests/TestGenerators.java b/test/hotspot/jtreg/testlibrary_tests/generators/tests/TestGenerators.java index f949f99c03578..8ad0c17ba98e6 100644 --- a/test/hotspot/jtreg/testlibrary_tests/generators/tests/TestGenerators.java +++ b/test/hotspot/jtreg/testlibrary_tests/generators/tests/TestGenerators.java @@ -391,13 +391,13 @@ static void testEmptyGenerators() { Asserts.assertThrows(EmptyGeneratorException.class, () -> G.uniformDoubles(1, 0)); Asserts.assertNotNull(G.uniformDoubles(0, 1)); - Asserts.assertThrows(EmptyGeneratorException.class, () -> G.uniformDoubles(0, 0)); + Asserts.assertNotNull(G.uniformDoubles(0, 0)); Asserts.assertThrows(EmptyGeneratorException.class, () -> G.uniformDoubles(0, 1).restricted(1.1d, 2.4d)); Asserts.assertNotNull(G.uniformDoubles(0, 1).restricted(0.9d, 2.4d)); Asserts.assertThrows(EmptyGeneratorException.class, () -> G.uniformFloats(1, 0)); Asserts.assertNotNull(G.uniformFloats(0, 1)); - Asserts.assertThrows(EmptyGeneratorException.class, () -> G.uniformFloats(0, 0)); + Asserts.assertNotNull(G.uniformFloats(0, 0)); Asserts.assertThrows(EmptyGeneratorException.class, () -> G.uniformFloats(0, 1).restricted(1.1f, 2.4f)); Asserts.assertNotNull(G.uniformFloats(0, 1).restricted(0.9f, 2.4f)); @@ -592,13 +592,8 @@ static void testFuzzy() { var floatBoundGen = G.uniformFloats(); for (int j = 0; j < 500; j++) { - float lo = 1, hi = 0; - // Failure of a single round is very rare, repeated failure even rarer. - while (lo >= hi) { - float a = floatBoundGen.next(), b = floatBoundGen.next(); - lo = Math.min(a, b); - hi = Math.max(a, b); - } + float a = floatBoundGen.next(), b = floatBoundGen.next(); + float lo = Math.min(a, b), hi = Math.max(a, b); var gb = G.uniformFloats(lo, hi); for (int i = 0; i < 10_000; i++) { float x = gb.next(); @@ -609,13 +604,8 @@ static void testFuzzy() { var doubleBoundGen = G.uniformDoubles(); for (int j = 0; j < 500; j++) { - double lo = 1, hi = 0; - // Failure of a single round is very rare, repeated failure even rarer. - while (lo >= hi) { - double a = doubleBoundGen.next(), b = doubleBoundGen.next(); - lo = Math.min(a, b); - hi = Math.max(a, b); - } + double a = doubleBoundGen.next(), b = doubleBoundGen.next(); + double lo = Math.min(a, b), hi = Math.max(a, b); var gb = G.uniformDoubles(lo, hi); for (int i = 0; i < 10_000; i++) { double x = gb.next(); diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestScenariosCrossProduct.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestScenariosCrossProduct.java index 46813bbff78ff..496fcbddb0fe0 100644 --- a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestScenariosCrossProduct.java +++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestScenariosCrossProduct.java @@ -23,22 +23,15 @@ package ir_framework.tests; -import java.io.ByteArrayOutputStream; -import java.io.PrintStream; -import java.lang.reflect.Field; -import java.util.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Collectors; +import java.util.Set; import compiler.lib.ir_framework.*; -import compiler.lib.ir_framework.shared.TestFormatException; import compiler.lib.ir_framework.shared.TestRunException; +import compiler.lib.ir_framework.shared.TestFormatException; import jdk.test.lib.Asserts; /* * @test - * @bug 8365262 8369232 * @requires vm.debug == true & vm.compMode != "Xint" & vm.compiler2.enabled & vm.flagless * @summary Test cross product scenarios with the framework. * @library /test/lib /testlibrary_tests / @@ -46,20 +39,29 @@ */ public class TestScenariosCrossProduct { + static void hasNFailures(String s, int count) { + if (!s.matches("The following scenarios have failed: (#[0-9](, )?){" + count + "}. Please check stderr for more information.")) { + throw new RuntimeException("Expected " + count + " failures in \"" + s + "\""); + } + } public static void main(String[] args) { - expectFormatFailure((Set[]) null); - expectFormatFailure(Set.of("foo", "bar"), null); - + // Test argument handling + try { + TestFramework t = new TestFramework(); + t.addCrossProductScenarios((Set[]) null); + Asserts.fail("Should have thrown exception"); + } catch (TestFormatException e) {} + try { + TestFramework t = new TestFramework(); + t.addCrossProductScenarios(Set.of("foo", "bar"), null); + Asserts.fail("Should have thrown exception"); + } catch (TestFormatException e) {} try { TestFramework t = new TestFramework(); t.addCrossProductScenarios(Set.of("blub"), Set.of("foo", null)); - shouldHaveThrown(); - } catch (NullPointerException _) { - // Expected: Set.of prevents null elements - } - - + Asserts.fail("Should have thrown exception"); + } catch (NullPointerException e) {} // Set.of prevents null elements try { TestFramework t = new TestFramework(); t.addCrossProductScenarios(); @@ -68,291 +70,95 @@ public static void main(String[] args) { } // Single set should test all flags in the set by themselves. - new TestCase() - .inputFlags(Set.of( - Set.of("-XX:TLABRefillWasteFraction=51", - "-XX:TLABRefillWasteFraction=53", - "-XX:TLABRefillWasteFraction=64") - ) - ) - .expectedScenariosWithFlags(Set.of( - Set.of("-XX:TLABRefillWasteFraction=51"), - Set.of("-XX:TLABRefillWasteFraction=53"), - Set.of("-XX:TLABRefillWasteFraction=64") - )) - .run(); - - // The cross product of a set with one element and a set with three elements is three sets. - new TestCase() - .inputFlags(Set.of( - Set.of("-XX:TLABRefillWasteFraction=53"), - Set.of("-XX:+UseNewCode", "-XX:+UseNewCode2", "-XX:+UseNewCode3") - ) - ) - .expectedScenariosWithFlags(Set.of( - Set.of("-XX:TLABRefillWasteFraction=53", "-XX:+UseNewCode"), - Set.of("-XX:TLABRefillWasteFraction=53", "-XX:+UseNewCode2"), - Set.of("-XX:TLABRefillWasteFraction=53", "-XX:+UseNewCode3") - )) - .run(); - - - // The cross product of two sets with two elements is four sets. - new TestCase() - .inputFlags(Set.of( - Set.of("-XX:TLABRefillWasteFraction=53", "-XX:TLABRefillWasteFraction=64"), - Set.of("-XX:+UseNewCode", "-XX:-UseNewCode") - ) - ) - .expectedScenariosWithFlags(Set.of( - Set.of("-XX:TLABRefillWasteFraction=53", "-XX:+UseNewCode"), - Set.of("-XX:TLABRefillWasteFraction=53", "-XX:-UseNewCode"), - Set.of("-XX:TLABRefillWasteFraction=64", "-XX:+UseNewCode"), - Set.of("-XX:TLABRefillWasteFraction=64", "-XX:-UseNewCode") - )) - .run(); - - - // Test with a pair of flags. - new TestCase() - .inputFlags(Set.of( - Set.of("-XX:TLABRefillWasteFraction=50 -XX:+UseNewCode", "-XX:TLABRefillWasteFraction=40"), - Set.of("-XX:+UseNewCode2") - ) - ) - .expectedScenariosWithFlags(Set.of( - Set.of("-XX:TLABRefillWasteFraction=50", "-XX:+UseNewCode", "-XX:+UseNewCode2"), - Set.of("-XX:TLABRefillWasteFraction=40", "-XX:+UseNewCode2") - )) - .run(); - - // Test with an empty string, resulting in 6 scenarios. - new TestCase() - .inputFlags(Set.of( - Set.of("", "-XX:TLABRefillWasteFraction=51", "-XX:TLABRefillWasteFraction=53"), - Set.of("-XX:+UseNewCode", "-XX:+UseNewCode2") - ) - ) - .expectedScenariosWithFlags(Set.of( - Set.of("-XX:+UseNewCode"), - Set.of("-XX:+UseNewCode2"), - Set.of("-XX:TLABRefillWasteFraction=51", "-XX:+UseNewCode"), - Set.of("-XX:TLABRefillWasteFraction=51", "-XX:+UseNewCode2"), - Set.of("-XX:TLABRefillWasteFraction=53", "-XX:+UseNewCode"), - Set.of("-XX:TLABRefillWasteFraction=53", "-XX:+UseNewCode2") - )) - .run(); - - // Test with 3 input sets which equals to 2x2x2 = 8 scenarios. - new TestCase() - .inputFlags(Set.of( - Set.of("-XX:TLABRefillWasteFraction=51", - "-XX:TLABRefillWasteFraction=53"), - Set.of("-XX:+UseNewCode", - "-XX:-UseNewCode"), - Set.of("-XX:+UseNewCode2", - "-XX:-UseNewCode2") - ) - ) - .expectedScenariosWithFlags(Set.of( - Set.of("-XX:TLABRefillWasteFraction=51", "-XX:+UseNewCode", "-XX:+UseNewCode2"), - Set.of("-XX:TLABRefillWasteFraction=53", "-XX:+UseNewCode", "-XX:+UseNewCode2"), - Set.of("-XX:TLABRefillWasteFraction=51", "-XX:-UseNewCode", "-XX:+UseNewCode2"), - Set.of("-XX:TLABRefillWasteFraction=53", "-XX:-UseNewCode", "-XX:+UseNewCode2"), - Set.of("-XX:TLABRefillWasteFraction=51", "-XX:+UseNewCode", "-XX:-UseNewCode2"), - Set.of("-XX:TLABRefillWasteFraction=53", "-XX:+UseNewCode", "-XX:-UseNewCode2"), - Set.of("-XX:TLABRefillWasteFraction=51", "-XX:-UseNewCode", "-XX:-UseNewCode2"), - Set.of("-XX:TLABRefillWasteFraction=53", "-XX:-UseNewCode", "-XX:-UseNewCode2") - )) - .run(); - - TestFramework testFramework = new TestFramework(); - testFramework.addScenarios(new Scenario(0, "-XX:TLABRefillWasteFraction=50", "-XX:+UseNewCode")); - testFramework.addCrossProductScenarios(Set.of("-XX:TLABRefillWasteFraction=51", "-XX:TLABRefillWasteFraction=53"), - Set.of("-XX:+UseNewCode", "-XX:+UseNewCode2")); try { - testFramework.addScenarios(new Scenario(4, "-XX:+UseNewCode3")); // fails because index 4 is already used - shouldHaveThrown(); - } catch (TestFormatException _) { - // Expected. + TestFramework t1 = new TestFramework(); + t1.addCrossProductScenarios(Set.of("-XX:TLABRefillWasteFraction=51", + "-XX:TLABRefillWasteFraction=53", + "-XX:TLABRefillWasteFraction=64")); + t1.start(); + Asserts.fail("Should have thrown exception"); + } catch (TestRunException e) { + hasNFailures(e.getMessage(), 3); } - testFramework.addScenarios(new Scenario(5, "-XX:+UseNewCode3")); - new TestCase() - .expectedScenariosWithFlags(Set.of( - Set.of("-XX:TLABRefillWasteFraction=50", "-XX:+UseNewCode"), - Set.of("-XX:TLABRefillWasteFraction=51", "-XX:+UseNewCode"), - Set.of("-XX:TLABRefillWasteFraction=51", "-XX:+UseNewCode2"), - Set.of("-XX:TLABRefillWasteFraction=53", "-XX:+UseNewCode"), - Set.of("-XX:TLABRefillWasteFraction=53", "-XX:+UseNewCode2"), - Set.of("-XX:+UseNewCode3") - )) - .runWithPreAddedScenarios(testFramework); - - runEndToEndTest(); - } - - private static void expectFormatFailure(Set... flagSets) { - TestFramework testFramework = new TestFramework(); + // The cross product of a set with one element and a set with three elements is three sets. try { - testFramework.addCrossProductScenarios(flagSets); - shouldHaveThrown(); - } catch (TestFormatException _) { - // Expected. - } - } - - private static void shouldHaveThrown() { - Asserts.fail("Should have thrown exception"); - } - - static class TestCase { - private Set> inputFlags; - private Set> expectedScenariosWithFlags; - - public TestCase inputFlags(Set> inputFlags) { - this.inputFlags = inputFlags; - return this; - } - - public TestCase expectedScenariosWithFlags(Set> expectedScenariosWithFlags) { - this.expectedScenariosWithFlags = expectedScenariosWithFlags; - return this; - } - - public void run() { - TestFramework testFramework = new TestFramework(); - testFramework.addCrossProductScenarios(inputFlags.toArray(new Set[0])); - runWithPreAddedScenarios(testFramework); - } - - public void runWithPreAddedScenarios(TestFramework testFramework) { - List scenariosFromCrossProduct = getScenarios(testFramework); - assertScenarioCount(expectedScenariosWithFlags.size(), scenariosFromCrossProduct); - assertScenariosWithFlags(scenariosFromCrossProduct, expectedScenariosWithFlags); - assertSameResultWhenManuallyAdding(scenariosFromCrossProduct, expectedScenariosWithFlags); - } - - private static void assertScenarioCount(int expectedCount, List scenarios) { - Asserts.assertEQ(expectedCount, scenarios.size(), "Scenario count is off"); - } - - /** - * Check that the added scenarios to the IR framework with TestFramework.addCrossProductScenarios() - * (i.e. 'scenariosFromCrossProduct') match the expected flag combos (i.e. 'expectedScenariosWithFlags'). - */ - private static void assertScenariosWithFlags(List scenariosFromCrossProduct, - Set> expectedScenariosWithFlags) { - for (Set expectedScenarioFlags : expectedScenariosWithFlags) { - if (scenariosFromCrossProduct.stream() - .map(Scenario::getFlags) - .map(Set::copyOf) - .anyMatch(flags -> flags.equals(expectedScenarioFlags))) { - continue; - } - System.err.println("Scenarios from cross product:"); - for (Scenario s : scenariosFromCrossProduct) { - System.err.println(Arrays.toString(s.getFlags().toArray())); - } - throw new RuntimeException("Could not find a scenario with the provided flags: " + Arrays.toString(expectedScenarioFlags.toArray())); - } - } - - /** - * Add scenarios for the provided flag sets in 'expectedScenariosWithFlags' by using TestFramework.addScenarios(). - * We should end up with the same scenarios as if we added them with TestFramework.addCrossProductScenarios(). - * This is verified by this method by comparing the flags of the scenarios, ignoring scenario indices. - */ - private static void assertSameResultWhenManuallyAdding(List scenariosFromCrossProduct, - Set> expectedScenariosWithFlags) { - List expectedScenarios = getScenariosWithFlags(expectedScenariosWithFlags); - List fetchedScenarios = addScenariosAndFetchFromFramework(expectedScenarios); - assertSameScenarios(scenariosFromCrossProduct, fetchedScenarios); - } - - private static List getScenariosWithFlags(Set> expectedScenariosWithFlags) { - List expecedScenarioList = new ArrayList<>(); - int index = -1; // Use some different indices - should not matter what we choose. - for (Set expectedScenarioFlags : expectedScenariosWithFlags) { - expecedScenarioList.add(new Scenario(index--, expectedScenarioFlags.toArray(new String[0]))); - } - return expecedScenarioList; + TestFramework t2 = new TestFramework(); + t2.addCrossProductScenarios(Set.of("-XX:TLABRefillWasteFraction=53"), + Set.of("-XX:+UseNewCode", "-XX:+UseNewCode2", "-XX:+UseNewCode3")); + t2.start(); + Asserts.fail("Should have thrown exception"); + } catch (TestRunException e) { + hasNFailures(e.getMessage(), 3); } - private static List addScenariosAndFetchFromFramework(List expecedScenarioList) { - TestFramework testFramework = new TestFramework(); - testFramework.addScenarios(expecedScenarioList.toArray(new Scenario[0])); - return getScenarios(testFramework); + // The cross product of two sets with two elements is four sets. + try { + TestFramework t3 = new TestFramework(); + t3.addCrossProductScenarios(Set.of("-XX:TLABRefillWasteFraction=53", "-XX:TLABRefillWasteFraction=64"), + Set.of("-XX:+UseNewCode", "-XX:-UseNewCode")); + t3.start(); + Asserts.fail("Should have thrown exception"); + } catch (TestRunException e) { + hasNFailures(e.getMessage(), 4); } - private static void assertSameScenarios(List scenariosFromCrossProduct, - List expectedScenarios) { - assertScenariosWithFlags(scenariosFromCrossProduct, fetchFlags(expectedScenarios)); + // Test with a pair of flags. + try { + TestFramework t4 = new TestFramework(); + t4.addCrossProductScenarios(Set.of("-XX:TLABRefillWasteFraction=50 -XX:+UseNewCode", "-XX:TLABRefillWasteFraction=40"), + Set.of("-XX:+UseNewCode2")); + t4.start(); + Asserts.fail("Should have thrown exception"); + } catch (TestRunException e) { + hasNFailures(e.getMessage(), 1); } - private static Set> fetchFlags(List scenarios) { - return scenarios.stream() - .map(scenario -> new HashSet<>(scenario.getFlags())) - .collect(Collectors.toSet()); + // Test with an empty string. All 6 scenarios fail because 64 is the default value for TLABRefillWasteFraction. + try { + TestFramework t5 = new TestFramework(); + t5.addCrossProductScenarios(Set.of("", "-XX:TLABRefillWasteFraction=51", "-XX:TLABRefillWasteFraction=53"), + Set.of("-XX:+UseNewCode", "-XX:+UseNewCode2")); + t5.start(); + Asserts.fail("Should have thrown exception"); + } catch (TestRunException e) { + hasNFailures(e.getMessage(), 6); } - } - private static List getScenarios(TestFramework testFramework) { - Field field; try { - field = TestFramework.class.getDeclaredField("scenarios"); - field.setAccessible(true); - return (List)field.get(testFramework); - } catch (NoSuchFieldException | IllegalAccessException e) { - throw new RuntimeException(e); + TestFramework t6 = new TestFramework(); + t6.addScenarios(new Scenario(0, "-XX:TLABRefillWasteFraction=50", "-XX:+UseNewCode")); // failPair + t6.addCrossProductScenarios(Set.of("-XX:TLABRefillWasteFraction=51", "-XX:TLABRefillWasteFraction=53"), + Set.of("-XX:+UseNewCode", "-XX:+UseNewCode2")); + try { + t6.addScenarios(new Scenario(4, "-XX:+UseNewCode3")); // fails because index 4 is already used + Asserts.fail("Should have thrown exception"); + } catch (TestFormatException e) {} + t6.addScenarios(new Scenario(5, "-XX:+UseNewCode3")); // fail default + t6.start(); + Asserts.fail("Should have thrown exception"); + } catch (TestRunException e) { + hasNFailures(e.getMessage(), 6); } } - /** - * Also run a simple end-to-end test to sanity check the API method. We capture the stderr to fetch the - * scenario flags. - */ - private static void runEndToEndTest() { - TestFramework testFramework = new TestFramework(); - - // Capture stderr - PrintStream originalErr = System.err; - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - PrintStream printStream = new PrintStream(outputStream); - System.setErr(printStream); + @Test + @IR(applyIf = {"TLABRefillWasteFraction", "64"}, counts = {IRNode.CALL, "1"}) + public void failDefault() { + } - try { - testFramework - .addCrossProductScenarios(Set.of("-XX:+UseNewCode", "-XX:-UseNewCode"), - Set.of("-XX:+UseNewCode2", "-XX:-UseNewCode2")) - .addFlags() - .start(); - shouldHaveThrown(); - } catch (TestRunException e) { - // Expected. - System.setErr(originalErr); - Asserts.assertTrue(e.getMessage().contains("The following scenarios have failed: #0, #1, #2, #3.")); - String stdErr = outputStream.toString(); - Asserts.assertTrue(stdErr.contains("Scenario flags: [-XX:+UseNewCode, -XX:+UseNewCode2]")); - Asserts.assertTrue(stdErr.contains("Scenario flags: [-XX:-UseNewCode, -XX:-UseNewCode2]")); - Asserts.assertTrue(stdErr.contains("Scenario flags: [-XX:+UseNewCode, -XX:-UseNewCode2]")); - Asserts.assertTrue(stdErr.contains("Scenario flags: [-XX:-UseNewCode, -XX:+UseNewCode2]")); - Asserts.assertEQ(4, scenarioCount(stdErr)); - } + @Test + @IR(applyIf = {"TLABRefillWasteFraction", "51"}, counts = {IRNode.CALL, "1"}) + public void fail1() { } - public static int scenarioCount(String stdErr) { - Pattern pattern = Pattern.compile("Scenario flags"); - Matcher matcher = pattern.matcher(stdErr); - int count = 0; - while (matcher.find()) { - count++; - } - return count; + @Test + @IR(applyIf = {"TLABRefillWasteFraction", "53"}, counts = {IRNode.CALL, "1"}) + public void fail2() { } @Test - public void endToEndTest() { - throw new RuntimeException("executed test"); + @IR(applyIfAnd = {"TLABRefillWasteFraction", "50", "UseNewCode", "true"}, counts = {IRNode.CALL, "1"}) + public void failPair() { } } diff --git a/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestExpressions.java b/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestExpressions.java index c21d2492fc768..6e11a7050540d 100644 --- a/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestExpressions.java +++ b/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestExpressions.java @@ -70,52 +70,29 @@ public static String generate(CompileFramework comp) { var withConstantsTemplate = Template.make("expression", (Expression expression) -> { // Create a token: fill the expression with a fixed set of constants. // We then use the same token with the same constants, once compiled and once not compiled. - // - // Some expressions can throw Exceptions. We have to catch them. In such a case, we return - // the Exception instead of the value from the expression, and compare the Exceptions. - // - // Some Expressions do not have a deterministic result. For example, different NaN or - // precision results from some operators. We only compare the results if we know that the - // result is deterministically the same. TemplateToken expressionToken = expression.asToken(expression.argumentTypes.stream().map(t -> t.con()).toList()); return body( let("returnType", expression.returnType), """ @Test public static void $primitiveConTest() { - Object v0 = ${primitiveConTest}_compiled(); - Object v1 = ${primitiveConTest}_reference(); - """, - expression.info.isResultDeterministic ? "Verify.checkEQ(v0, v1);\n" : "", - """ + #returnType v0 = ${primitiveConTest}_compiled(); + #returnType v1 = ${primitiveConTest}_reference(); + Verify.checkEQ(v0, v1); } @DontInline - public static Object ${primitiveConTest}_compiled() { - try { + public static #returnType ${primitiveConTest}_compiled() { """, - "return ", expressionToken, ";\n", - expression.info.exceptions.stream().map(exception -> - "} catch (" + exception + " e) { return e;\n" - ).toList(), + "return ", expressionToken, ";\n", """ - } finally { - // Just so that javac is happy if there are no exceptions to catch. - } } @DontCompile - public static Object ${primitiveConTest}_reference() { - try { + public static #returnType ${primitiveConTest}_reference() { """, - "return ", expressionToken, ";\n", - expression.info.exceptions.stream().map(exception -> - "} catch (" + exception + " e) { return e;\n" - ).toList(), + "return ", expressionToken, ";\n", """ - } finally { - // Just so that javac is happy if there are no exceptions to catch. - } } """ ); diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/GenClassPoolJar.java b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/GenClassPoolJar.java index 511db8b8ed1c9..cea00fc2efc3a 100644 --- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/GenClassPoolJar.java +++ b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/GenClassPoolJar.java @@ -26,9 +26,6 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; -import java.lang.classfile.ClassFile; -import java.lang.classfile.ClassTransform; -import java.lang.constant.ClassDesc; import java.nio.file.FileVisitResult; import java.nio.file.FileVisitor; import java.nio.file.Files; @@ -45,6 +42,11 @@ import javax.tools.JavaFileObject; import javax.tools.StandardJavaFileManager; import javax.tools.ToolProvider; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.Opcodes; + /** * Class that imitates shell script to produce jar file with many similar * classes inside. @@ -259,9 +261,28 @@ public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOEx * @return new class file to write into class */ byte[] morphClass(byte[] classToMorph, String newName) { - var context = ClassFile.of(); - return context.transformClass(context.parse(classToMorph), - ClassDesc.ofInternalName(newName), - ClassTransform.ACCEPT_ALL); + ClassReader cr = new ClassReader(classToMorph); + ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS); + ClassVisitor cv = new ClassRenamer(cw, newName); + cr.accept(cv, 0); + return cw.toByteArray(); } + + /** + * Visitor to rename class. + */ + static class ClassRenamer extends ClassVisitor implements Opcodes { + private final String newName; + + public ClassRenamer(ClassVisitor cv, String newName) { + super(ASM4, cv); + this.newName = newName; + } + + @Override + public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { + cv.visit(version, access, newName, signature, superName, interfaces); + } + + } } diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_inMemoryCompilation_keep_cl/TestDescription.java b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_inMemoryCompilation_keep_cl/TestDescription.java index 5337aa73d2e17..19b2a94078867 100644 --- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_inMemoryCompilation_keep_cl/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_inMemoryCompilation_keep_cl/TestDescription.java @@ -30,6 +30,7 @@ * VM Testbase keywords: [gc, stress, stressopt, nonconcurrent, javac] * * @modules java.base/jdk.internal.misc + * @library /testlibrary/asm * @library /vmTestbase * /test/lib * diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_inMemoryCompilation_keep_class/TestDescription.java b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_inMemoryCompilation_keep_class/TestDescription.java index 75d45dda2fef3..b84411234a5a5 100644 --- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_inMemoryCompilation_keep_class/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_inMemoryCompilation_keep_class/TestDescription.java @@ -30,6 +30,7 @@ * VM Testbase keywords: [gc, stress, stressopt, nonconcurrent, javac] * * @modules java.base/jdk.internal.misc + * @library /testlibrary/asm * @library /vmTestbase * /test/lib * diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_inMemoryCompilation_keep_obj/TestDescription.java b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_inMemoryCompilation_keep_obj/TestDescription.java index aceade65a660f..f0cc45744c425 100644 --- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_inMemoryCompilation_keep_obj/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_inMemoryCompilation_keep_obj/TestDescription.java @@ -30,6 +30,7 @@ * VM Testbase keywords: [gc, stress, stressopt, nonconcurrent, javac] * * @modules java.base/jdk.internal.misc + * @library /testlibrary/asm * @library /vmTestbase * /test/lib * diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_keep_cl/TestDescription.java b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_keep_cl/TestDescription.java index a2547a7556f31..48f1680897f6b 100644 --- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_keep_cl/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_keep_cl/TestDescription.java @@ -30,6 +30,7 @@ * VM Testbase keywords: [gc, stress, stressopt, nonconcurrent, javac] * * @modules java.base/jdk.internal.misc + * @library /testlibrary/asm * @library /vmTestbase * /test/lib * diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_keep_class/TestDescription.java b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_keep_class/TestDescription.java index d822f65034dc0..68263db73ac1c 100644 --- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_keep_class/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_keep_class/TestDescription.java @@ -30,6 +30,7 @@ * VM Testbase keywords: [gc, stress, stressopt, nonconcurrent, javac] * * @modules java.base/jdk.internal.misc + * @library /testlibrary/asm * @library /vmTestbase * /test/lib * diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_keep_obj/TestDescription.java b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_keep_obj/TestDescription.java index e875b964f0fc3..4ee02a649d3d4 100644 --- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_keep_obj/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_keep_obj/TestDescription.java @@ -30,6 +30,7 @@ * VM Testbase keywords: [gc, stress, stressopt, nonconcurrent, javac] * * @modules java.base/jdk.internal.misc + * @library /testlibrary/asm * @library /vmTestbase * /test/lib * diff --git a/test/hotspot/jtreg/vmTestbase/gc/vector/CircularListLow/TestDescription.java b/test/hotspot/jtreg/vmTestbase/gc/vector/CircularListLow/TestDescription.java index 68fe6779e997d..252e3a2d40f92 100644 --- a/test/hotspot/jtreg/vmTestbase/gc/vector/CircularListLow/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/gc/vector/CircularListLow/TestDescription.java @@ -31,5 +31,6 @@ * * @library /vmTestbase * /test/lib + * @requires vm.gc != "Serial" * @run main/othervm/timeout=480 gc.vector.SimpleGC.SimpleGC -ms low -gp circularList(low) */ diff --git a/test/hotspot/jtreg/vmTestbase/gc/vector/LinearListLow/TestDescription.java b/test/hotspot/jtreg/vmTestbase/gc/vector/LinearListLow/TestDescription.java index 8ae86af035db6..bd094045abf0f 100644 --- a/test/hotspot/jtreg/vmTestbase/gc/vector/LinearListLow/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/gc/vector/LinearListLow/TestDescription.java @@ -31,5 +31,6 @@ * * @library /vmTestbase * /test/lib + * @requires vm.gc != "Serial" * @run main/othervm gc.vector.SimpleGC.SimpleGC -ms low -gp linearList(low) */ diff --git a/test/hotspot/jtreg/vmTestbase/metaspace/stressHierarchy/common/PerformChecksHelper.java b/test/hotspot/jtreg/vmTestbase/metaspace/stressHierarchy/common/PerformChecksHelper.java index e660dac4fd57f..3d57bfb6ea9ee 100644 --- a/test/hotspot/jtreg/vmTestbase/metaspace/stressHierarchy/common/PerformChecksHelper.java +++ b/test/hotspot/jtreg/vmTestbase/metaspace/stressHierarchy/common/PerformChecksHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -136,17 +136,8 @@ private void callMethods(Class clazz) } } } - } catch (InvocationTargetException ite) { - Throwable cause = ite.getCause(); - if (cause != null && (cause instanceof OutOfMemoryError) && cause.getMessage().contains("Metaspace")) { - // avoid string concatenation, which may create more classes. - System.out.println("Got OOME in metaspace in PerformChecksHelper.callMethods(Class clazz). "); - System.out.println("This is possible with -triggerUnloadingByFillingMetaspace"); - } else { - throw ite; - } } catch (OutOfMemoryError e) { - if (e.getMessage().contains("Metaspace")) { + if (e.getMessage().trim().toLowerCase().contains("metaspace")) { // avoid string concatenation, which may create more classes. System.out.println("Got OOME in metaspace in PerformChecksHelper.callMethods(Class clazz). "); System.out.println("This is possible with -triggerUnloadingByFillingMetaspace"); diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetClassFields/getclfld007.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetClassFields/getclfld007.java index 300966c04dd8c..6d79e479b97a2 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetClassFields/getclfld007.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetClassFields/getclfld007.java @@ -25,12 +25,14 @@ import java.io.PrintStream; import java.io.InputStream; -import java.lang.classfile.ClassFile; -import java.lang.classfile.ClassModel; -import java.lang.classfile.FieldModel; import java.util.List; import java.util.ArrayList; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.Opcodes; + public class getclfld007 { @@ -77,29 +79,44 @@ public static int run(String args[], PrintStream out) { static void check(Class cls) throws Exception { - List fields = getFields(cls); + FieldExplorer explorer = new FieldExplorer(cls); + List fields = explorer.get(); check(cls, fields.toArray(new String[0])); } - private static InputStream getClassBytes(Class cls) throws Exception { - String clsName = cls.getName(); - String clsPath = clsName.replace('.', '/') + ".class"; - return cls.getClassLoader().getResourceAsStream(clsPath); - } + // helper class to get list of the class fields + // in the order they appear in the class file + static class FieldExplorer extends ClassVisitor { + private final Class cls; + private List fieldNameAndSig = new ArrayList<>(); + private FieldExplorer(Class cls) { + super(Opcodes.ASM7); + this.cls = cls; + } + + @Override + public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) { + System.out.println(" field '" + name + "', type = " + descriptor); + fieldNameAndSig.add(name); + fieldNameAndSig.add(descriptor); + return super.visitField(access, name, descriptor, signature, value); + } + + private InputStream getClassBytes() throws Exception { + String clsName = cls.getName(); + String clsPath = clsName.replace('.', '/') + ".class"; + return cls.getClassLoader().getResourceAsStream(clsPath); + } - // get list of the class fields in the order they appear in the class file - // each field is represented by 2 Strings in the list: name and type descriptor - public static List getFields(Class cls) throws Exception { - System.out.println("Class " + cls.getName()); - List fieldNameAndSig = new ArrayList<>(); - try (InputStream classBytes = getClassBytes(cls)) { - ClassModel classModel = ClassFile.of().parse(classBytes.readAllBytes()); - for (FieldModel field : classModel.fields()) { - fieldNameAndSig.add(field.fieldName().stringValue()); - fieldNameAndSig.add(field.fieldType().stringValue()); + // each field is represented by 2 Strings in the list: name and type descriptor + public List get() throws Exception { + System.out.println("Class " + cls.getName()); + try (InputStream classBytes = getClassBytes()) { + ClassReader classReader = new ClassReader(classBytes); + classReader.accept(this, 0); } + return fieldNameAndSig; } - return fieldNameAndSig; } static class InnerClass1 { diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetCurrentThreadCpuTime/curthrcputime001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetCurrentThreadCpuTime/curthrcputime001/TestDescription.java index ba09ff735d804..0b7e1d2a89ede 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetCurrentThreadCpuTime/curthrcputime001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetCurrentThreadCpuTime/curthrcputime001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -71,7 +71,6 @@ * COMMENTS * Fixed the 4968019, 5006885 bugs. * - * @requires test.thread.factory == null * @library /vmTestbase * /test/lib * @build nsk.jvmti.GetCurrentThreadCpuTime.curthrcputime001 diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetThreadCpuTime/thrcputime001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetThreadCpuTime/thrcputime001/TestDescription.java index b935639e18308..cf0fe3e5d2d48 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetThreadCpuTime/thrcputime001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetThreadCpuTime/thrcputime001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 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 @@ -71,7 +71,6 @@ * COMMENTS * Fixed the 4968019, 5006885 bugs. * - * @requires test.thread.factory == null * @library /vmTestbase * /test/lib * @build nsk.jvmti.GetThreadCpuTime.thrcputime001 diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/contention/TC03/tc03t001.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/contention/TC03/tc03t001.java index eb202c87ef3df..4c7905809d978 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/contention/TC03/tc03t001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/contention/TC03/tc03t001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2018, 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 @@ -123,8 +123,6 @@ public int runIt(String argv[], PrintStream out) { /* =================================================================== */ class tc03t001Thread extends Thread { - // The thread name prefix is used to find thread from jvmti agent. - final static String threadNamePrefix = "Debuggee Thread"; Object lock1; Object lock2; @@ -132,7 +130,7 @@ class tc03t001Thread extends Thread { int lock2Counter = 0; public tc03t001Thread(Object o1, Object o2) { - super(threadNamePrefix + " " + o1 + o2); + super("Debuggee Thread " + o1 + o2); lock1 = o1; lock2 = o2; } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/contention/TC03/tc03t001/tc03t001.cpp b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/contention/TC03/tc03t001/tc03t001.cpp index 9ea61a27bc650..ff7d346d237a1 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/contention/TC03/tc03t001/tc03t001.cpp +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/contention/TC03/tc03t001/tc03t001.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,13 +41,10 @@ typedef struct { static jlong timeout = 0; /* test objects */ -static threadDesc *debuggee_threads = nullptr; -static jint debuggee_threads_cnt = 0; +static threadDesc *threadList = nullptr; +static jint threads_count = 0; static int numberOfDeadlocks = 0; -static const char* THREAD_NAME_PREFIX = "Debugee Thread"; -static const size_t THREAD_NAME_PREFIX_LEN = strlen(THREAD_NAME_PREFIX); - /* ========================================================================== */ static int printDeadlock(jvmtiEnv* jvmti, JNIEnv* jni, int dThread) { @@ -59,9 +56,9 @@ static int printDeadlock(jvmtiEnv* jvmti, JNIEnv* jni, int dThread) { NSK_DISPLAY1("Found deadlock #%d:\n", numberOfDeadlocks); for (pThread = dThread;;pThread = cThread) { - NSK_DISPLAY1(" \"%s\":\n", debuggee_threads[pThread].name); + NSK_DISPLAY1(" \"%s\":\n", threadList[pThread].name); if (!NSK_JVMTI_VERIFY( - jvmti->GetCurrentContendedMonitor(debuggee_threads[pThread].thread, &monitor))) + jvmti->GetCurrentContendedMonitor(threadList[pThread].thread, &monitor))) return NSK_FALSE; if (monitor != nullptr) { if (!NSK_JNI_VERIFY(jni, (klass = jni->GetObjectClass(monitor)) != nullptr)) @@ -77,8 +74,8 @@ static int printDeadlock(jvmtiEnv* jvmti, JNIEnv* jni, int dThread) { return NSK_FALSE; if (usageInfo.owner == nullptr) break; - for (cThread = 0; cThread < debuggee_threads_cnt; cThread++) { - if (jni->IsSameObject(debuggee_threads[cThread].thread, usageInfo.owner)) + for (cThread = 0; cThread < threads_count; cThread++) { + if (jni->IsSameObject(threadList[cThread].thread, usageInfo.owner)) break; } if (usageInfo.waiters != nullptr) { @@ -87,10 +84,10 @@ static int printDeadlock(jvmtiEnv* jvmti, JNIEnv* jni, int dThread) { if (usageInfo.notify_waiters != nullptr) { jvmti->Deallocate((unsigned char*)usageInfo.notify_waiters); } - if (!NSK_VERIFY(cThread != debuggee_threads_cnt)) + if (!NSK_VERIFY(cThread != threads_count)) return NSK_FALSE; NSK_DISPLAY1(" which is held by \"%s\"\n", - debuggee_threads[cThread].name); + threadList[cThread].name); if (cThread == dThread) break; } @@ -106,9 +103,8 @@ static int findDeadlockThreads(jvmtiEnv* jvmti, JNIEnv* jni) { int tDfn = 0, gDfn = 0; int pThread, cThread; int i; - int threads_count = 0; - NSK_DISPLAY0("Create debuggee_threads\n"); + NSK_DISPLAY0("Create threadList\n"); /* get all live threads */ if (!NSK_JVMTI_VERIFY(jvmti->GetAllThreads(&threads_count, &threads))) @@ -118,7 +114,7 @@ static int findDeadlockThreads(jvmtiEnv* jvmti, JNIEnv* jni) { return NSK_FALSE; if (!NSK_JVMTI_VERIFY( - jvmti->Allocate(threads_count*sizeof(threadDesc), (unsigned char**)&debuggee_threads))) + jvmti->Allocate(threads_count*sizeof(threadDesc), (unsigned char**)&threadList))) return NSK_FALSE; for (i = 0; i < threads_count; i++) { @@ -131,30 +127,22 @@ static int findDeadlockThreads(jvmtiEnv* jvmti, JNIEnv* jni) { NSK_DISPLAY3(" thread #%d (%s): %p\n", i, info.name, threads[i]); - if (!strncmp(info.name, THREAD_NAME_PREFIX, THREAD_NAME_PREFIX_LEN)) { - NSK_DISPLAY1("Skipping thread %s\n", info.name); - if (!NSK_JVMTI_VERIFY(jvmti->Deallocate((unsigned char*)info.name))) - return NSK_FALSE; - continue; - } - - debuggee_threads[debuggee_threads_cnt].thread = threads[i]; - debuggee_threads[debuggee_threads_cnt].dfn = -1; - debuggee_threads[debuggee_threads_cnt].name = info.name; - debuggee_threads_cnt++; + threadList[i].thread = threads[i]; + threadList[i].dfn = -1; + threadList[i].name = info.name; } /* deallocate thread list */ if (!NSK_JVMTI_VERIFY(jvmti->Deallocate((unsigned char*)threads))) return NSK_FALSE; - for (i = 0; i < debuggee_threads_cnt; i++) { - if (debuggee_threads[i].dfn < 0) { + for (i = 0; i < threads_count; i++) { + if (threadList[i].dfn < 0) { tDfn = gDfn; - debuggee_threads[i].dfn = gDfn++; + threadList[i].dfn = gDfn++; for (pThread = i;;pThread = cThread) { if (!NSK_JVMTI_VERIFY( - jvmti->GetCurrentContendedMonitor(debuggee_threads[pThread].thread, &monitor))) + jvmti->GetCurrentContendedMonitor(threadList[pThread].thread, &monitor))) return NSK_FALSE; if (monitor == nullptr) break; @@ -162,8 +150,8 @@ static int findDeadlockThreads(jvmtiEnv* jvmti, JNIEnv* jni) { return NSK_FALSE; if (usageInfo.owner == nullptr) break; - for (cThread = 0; cThread < debuggee_threads_cnt; cThread++) { - if (jni->IsSameObject(debuggee_threads[cThread].thread, usageInfo.owner)) + for (cThread = 0; cThread < threads_count; cThread++) { + if (jni->IsSameObject(threadList[cThread].thread, usageInfo.owner)) break; } if (usageInfo.waiters != nullptr) { @@ -172,10 +160,10 @@ static int findDeadlockThreads(jvmtiEnv* jvmti, JNIEnv* jni) { if (usageInfo.notify_waiters != nullptr) { jvmti->Deallocate((unsigned char*)usageInfo.notify_waiters); } - if (!NSK_VERIFY(cThread != debuggee_threads_cnt)) + if (!NSK_VERIFY(cThread != threads_count)) return NSK_FALSE; - if (debuggee_threads[cThread].dfn < 0) { - debuggee_threads[cThread].dfn = gDfn++; + if (threadList[cThread].dfn < 0) { + threadList[cThread].dfn = gDfn++; } else if (cThread == pThread) { break; } else { @@ -191,9 +179,9 @@ static int findDeadlockThreads(jvmtiEnv* jvmti, JNIEnv* jni) { } /* deallocate thread names */ - for (i = 0; i < debuggee_threads_cnt; i++) { - if (debuggee_threads[i].name != nullptr) { - if (!NSK_JVMTI_VERIFY(jvmti->Deallocate((unsigned char*)debuggee_threads[i].name))) + for (i = 0; i < threads_count; i++) { + if (threadList[i].name != nullptr) { + if (!NSK_JVMTI_VERIFY(jvmti->Deallocate((unsigned char*)threadList[i].name))) return NSK_FALSE; } } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/contention/TC03/tc03t002.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/contention/TC03/tc03t002.java index 852b915acd745..f4ca83c0b5461 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/contention/TC03/tc03t002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/contention/TC03/tc03t002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2018, 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 @@ -104,8 +104,7 @@ public int runIt(String argv[], PrintStream out) { /* =================================================================== */ class tc03t002Thread extends Thread { - // The thread name prefix is used to find thread from jvmti agent. - final static String threadNamePrefix = "Debuggee Thread"; + static Wicket startingBarrier = new Wicket(3); static Wicket lockingBarrier = new Wicket(3); Wicket waitingBarrier = new Wicket(); @@ -113,7 +112,7 @@ class tc03t002Thread extends Thread { Object lock2; public tc03t002Thread(Object o1, Object o2) { - super(threadNamePrefix + " " + o1 + o2); + super("Debuggee Thread " + o1 + o2); lock1 = o1; lock2 = o2; } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/contention/TC03/tc03t002/tc03t002.cpp b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/contention/TC03/tc03t002/tc03t002.cpp index 5d18d6c23afdb..11c74e3a9e2c4 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/contention/TC03/tc03t002/tc03t002.cpp +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/scenarios/contention/TC03/tc03t002/tc03t002.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,13 +41,10 @@ typedef struct { static jlong timeout = 0; /* test objects */ -static threadDesc *debuggee_threads = nullptr; -static jint debuggee_threads_cnt = 0; +static threadDesc *threadList = nullptr; +static jint threads_count = 0; static int numberOfDeadlocks = 0; -static const char* THREAD_NAME_PREFIX = "Debugee Thread"; -static const size_t THREAD_NAME_PREFIX_LEN = strlen(THREAD_NAME_PREFIX); - /* ========================================================================== */ static int printDeadlock(jvmtiEnv* jvmti, JNIEnv* jni, int dThread) { @@ -59,9 +56,9 @@ static int printDeadlock(jvmtiEnv* jvmti, JNIEnv* jni, int dThread) { NSK_DISPLAY1("Found deadlock #%d:\n", numberOfDeadlocks); for (pThread = dThread;;pThread = cThread) { - NSK_DISPLAY1(" \"%s\":\n", debuggee_threads[pThread].name); + NSK_DISPLAY1(" \"%s\":\n", threadList[pThread].name); if (!NSK_JVMTI_VERIFY( - jvmti->GetCurrentContendedMonitor(debuggee_threads[pThread].thread, &monitor))) + jvmti->GetCurrentContendedMonitor(threadList[pThread].thread, &monitor))) return NSK_FALSE; if (monitor != nullptr) { if (!NSK_JNI_VERIFY(jni, (klass = jni->GetObjectClass(monitor)) != nullptr)) @@ -77,8 +74,8 @@ static int printDeadlock(jvmtiEnv* jvmti, JNIEnv* jni, int dThread) { return NSK_FALSE; if (usageInfo.owner == nullptr) break; - for (cThread = 0; cThread < debuggee_threads_cnt; cThread++) { - if (jni->IsSameObject(debuggee_threads[cThread].thread, usageInfo.owner)) + for (cThread = 0; cThread < threads_count; cThread++) { + if (jni->IsSameObject(threadList[cThread].thread, usageInfo.owner)) break; } if (usageInfo.waiters != nullptr) { @@ -87,10 +84,10 @@ static int printDeadlock(jvmtiEnv* jvmti, JNIEnv* jni, int dThread) { if (usageInfo.notify_waiters != nullptr) { jvmti->Deallocate((unsigned char*)usageInfo.notify_waiters); } - if (!NSK_VERIFY(cThread != debuggee_threads_cnt)) + if (!NSK_VERIFY(cThread != threads_count)) return NSK_FALSE; NSK_DISPLAY1(" which is held by \"%s\"\n", - debuggee_threads[cThread].name); + threadList[cThread].name); if (cThread == dThread) break; } @@ -106,9 +103,8 @@ static int findDeadlockThreads(jvmtiEnv* jvmti, JNIEnv* jni) { int tDfn = 0, gDfn = 0; int pThread, cThread; int i; - int threads_count = 0; - NSK_DISPLAY0("Create debuggee_threads\n"); + NSK_DISPLAY0("Create threadList\n"); /* get all live threads */ if (!NSK_JVMTI_VERIFY(jvmti->GetAllThreads(&threads_count, &threads))) @@ -118,7 +114,7 @@ static int findDeadlockThreads(jvmtiEnv* jvmti, JNIEnv* jni) { return NSK_FALSE; if (!NSK_JVMTI_VERIFY( - jvmti->Allocate(threads_count*sizeof(threadDesc), (unsigned char**)&debuggee_threads))) + jvmti->Allocate(threads_count*sizeof(threadDesc), (unsigned char**)&threadList))) return NSK_FALSE; for (i = 0; i < threads_count; i++) { @@ -131,31 +127,22 @@ static int findDeadlockThreads(jvmtiEnv* jvmti, JNIEnv* jni) { NSK_DISPLAY3(" thread #%d (%s): %p\n", i, info.name, threads[i]); - if (!strncmp(info.name, THREAD_NAME_PREFIX, THREAD_NAME_PREFIX_LEN)) { - NSK_DISPLAY1("Skipping thread %s\n", info.name); - if (!NSK_JVMTI_VERIFY(jvmti->Deallocate((unsigned char*)info.name))) - return NSK_FALSE; - continue; - } - - debuggee_threads[debuggee_threads_cnt].thread = threads[i]; - debuggee_threads[debuggee_threads_cnt].dfn = -1; - debuggee_threads[debuggee_threads_cnt].name = info.name; - debuggee_threads_cnt++; + threadList[i].thread = threads[i]; + threadList[i].dfn = -1; + threadList[i].name = info.name; } /* deallocate thread list */ if (!NSK_JVMTI_VERIFY(jvmti->Deallocate((unsigned char*)threads))) return NSK_FALSE; - for (i = 0; i < debuggee_threads_cnt; i++) { - - if (debuggee_threads[i].dfn < 0) { + for (i = 0; i < threads_count; i++) { + if (threadList[i].dfn < 0) { tDfn = gDfn; - debuggee_threads[i].dfn = gDfn++; + threadList[i].dfn = gDfn++; for (pThread = i;;pThread = cThread) { if (!NSK_JVMTI_VERIFY( - jvmti->GetCurrentContendedMonitor(debuggee_threads[pThread].thread, &monitor))) + jvmti->GetCurrentContendedMonitor(threadList[pThread].thread, &monitor))) return NSK_FALSE; if (monitor == nullptr) break; @@ -163,8 +150,8 @@ static int findDeadlockThreads(jvmtiEnv* jvmti, JNIEnv* jni) { return NSK_FALSE; if (usageInfo.owner == nullptr) break; - for (cThread = 0; cThread < debuggee_threads_cnt; cThread++) { - if (jni->IsSameObject(debuggee_threads[cThread].thread, usageInfo.owner)) + for (cThread = 0; cThread < threads_count; cThread++) { + if (jni->IsSameObject(threadList[cThread].thread, usageInfo.owner)) break; } if (usageInfo.waiters != nullptr) { @@ -173,10 +160,10 @@ static int findDeadlockThreads(jvmtiEnv* jvmti, JNIEnv* jni) { if (usageInfo.notify_waiters != nullptr) { jvmti->Deallocate((unsigned char*)usageInfo.notify_waiters); } - if (!NSK_VERIFY(cThread != debuggee_threads_cnt)) + if (!NSK_VERIFY(cThread != threads_count)) return NSK_FALSE; - if (debuggee_threads[cThread].dfn < 0) { - debuggee_threads[cThread].dfn = gDfn++; + if (threadList[cThread].dfn < 0) { + threadList[cThread].dfn = gDfn++; } else if (cThread == pThread) { break; } else { @@ -192,9 +179,9 @@ static int findDeadlockThreads(jvmtiEnv* jvmti, JNIEnv* jni) { } /* deallocate thread names */ - for (i = 0; i < debuggee_threads_cnt; i++) { - if (debuggee_threads[i].name != nullptr) { - if (!NSK_JVMTI_VERIFY(jvmti->Deallocate((unsigned char*)debuggee_threads[i].name))) + for (i = 0; i < threads_count; i++) { + if (threadList[i].name != nullptr) { + if (!NSK_JVMTI_VERIFY(jvmti->Deallocate((unsigned char*)threadList[i].name))) return NSK_FALSE; } } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/ClassUnloader.java b/test/hotspot/jtreg/vmTestbase/nsk/share/ClassUnloader.java index e3b6693657c23..5ea01fb3af415 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/ClassUnloader.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/ClassUnloader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2023, 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,7 +28,7 @@ package nsk.share; -import java.lang.ref.PhantomReference; +import java.lang.ref.Cleaner; import java.util.*; import nsk.share.gc.gp.*; import nsk.share.test.ExecutionController; @@ -77,9 +77,19 @@ public class ClassUnloader { public static final String INTERNAL_CLASS_LOADER_NAME = "nsk.share.CustomClassLoader"; /** - * Phantom reference to the class loader. + * Whole amount of time in milliseconds to wait for class loader to be reclaimed. */ - private PhantomReference customClassLoaderPhantomRef = null; + private static final int WAIT_TIMEOUT = 15000; + + /** + * Sleep time in milliseconds for the loop waiting for the class loader to be reclaimed. + */ + private static final int WAIT_DELTA = 1000; + + /** + * Has class loader been reclaimed or not. + */ + volatile boolean is_reclaimed = false; /** * Current class loader used for loading classes. @@ -91,14 +101,6 @@ public class ClassUnloader { */ private Vector> classObjects = new Vector>(); - /** - * Has class loader been reclaimed or not. - */ - private boolean isClassLoaderReclaimed() { - return customClassLoaderPhantomRef != null - && customClassLoaderPhantomRef.refersTo(null); - } - /** * Class object of the first class been loaded with current class loader. * To get the rest loaded classes use getLoadedClass(int). @@ -136,7 +138,8 @@ public CustomClassLoader createClassLoader() { customClassLoader = new CustomClassLoader(); classObjects.removeAllElements(); - customClassLoaderPhantomRef = new PhantomReference<>(customClassLoader, null); + // Register a Cleaner to inform us when the class loader has been reclaimed. + Cleaner.create().register(customClassLoader, () -> { is_reclaimed = true; } ); return customClassLoader; } @@ -151,7 +154,8 @@ public void setClassLoader(CustomClassLoader customClassLoader) { this.customClassLoader = customClassLoader; classObjects.removeAllElements(); - customClassLoaderPhantomRef = new PhantomReference<>(customClassLoader, null); + // Register a Cleaner to inform us when the class loader has been reclaimed. + Cleaner.create().register(customClassLoader, () -> { is_reclaimed = true; } ); } /** @@ -240,15 +244,32 @@ public void loadClass(String className, String classDir) throws ClassNotFoundExc */ public boolean unloadClass(ExecutionController stresser) { + is_reclaimed = false; + // free references to class and class loader to be able for collecting by GC + long waitTimeout = (customClassLoader == null) ? 0 : WAIT_TIMEOUT; classObjects.removeAllElements(); customClassLoader = null; // force class unloading by eating memory pool eatMemory(stresser); + // give GC chance to run and wait for receiving reclaim notification + long timeToFinish = System.currentTimeMillis() + waitTimeout; + while (!is_reclaimed && System.currentTimeMillis() < timeToFinish) { + if (!stresser.continueExecution()) { + return false; + } + try { + // suspend thread for a while + Thread.sleep(WAIT_DELTA); + } catch (InterruptedException e) { + throw new Failure("Unexpected InterruptedException while class unloading: " + e); + } + } + // force GC to unload marked class loader and its classes - if (isClassLoaderReclaimed()) { + if (is_reclaimed) { Runtime.getRuntime().gc(); return true; } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/AbstractDebuggeeTest.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/AbstractDebuggeeTest.java index 74516fd5a69f9..0668297d211fa 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/AbstractDebuggeeTest.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/AbstractDebuggeeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2018, 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 @@ -149,11 +149,19 @@ public void loadTestClass(String className) { } } + public static final int MAX_UNLOAD_ATTEMPS = 5; + public void unloadTestClass(String className, boolean expectedUnloadingResult) { ClassUnloader classUnloader = loadedClasses.get(className); + int unloadAttemps = 0; + if (classUnloader != null) { - boolean wasUnloaded = classUnloader.unloadClass(); + boolean wasUnloaded = false; + + while (!wasUnloaded && (unloadAttemps++ < MAX_UNLOAD_ATTEMPS)) { + wasUnloaded = classUnloader.unloadClass(); + } if (wasUnloaded) loadedClasses.remove(className); @@ -175,6 +183,13 @@ public void unloadTestClass(String className, boolean expectedUnloadingResult) { } } + static public void sleep1sec() { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + } + } + private StateTestThread stateTestThread; public static final String COMMAND_QUIT = "quit"; @@ -347,6 +362,9 @@ public void forceGC() { eatMemory(); } + public void voidValueMethod() { + } + public void unexpectedException(Throwable t) { setSuccess(false); t.printStackTrace(log.getOutStream()); diff --git a/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Humongous_NonbranchyTree5M/TestDescription.java b/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Humongous_NonbranchyTree5M/TestDescription.java index a539fb7cea29a..1d5a6f0cf1188 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Humongous_NonbranchyTree5M/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/vm/gc/compact/Humongous_NonbranchyTree5M/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 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 @@ -36,7 +36,7 @@ * * @library /vmTestbase * /test/lib - * @run main/othervm/timeout=480 + * @run main/othervm * -XX:-UseGCOverheadLimit * vm.gc.compact.Compact * -gp nonbranchyTree(high) diff --git a/test/jdk/ProblemList-Virtual.txt b/test/jdk/ProblemList-Virtual.txt index dffbd4a952ec0..37c2c447efae8 100644 --- a/test/jdk/ProblemList-Virtual.txt +++ b/test/jdk/ProblemList-Virtual.txt @@ -30,6 +30,8 @@ com/sun/jdi/EATests.java#id0 8264699 generic- com/sun/jdi/ExceptionEvents.java 8278470 generic-all com/sun/jdi/RedefineCrossStart.java 8278470 generic-all +javax/management/remote/mandatory/loading/MissingClassTest.java 8145413 windows-x64 + java/lang/ScopedValue/StressStackOverflow.java#default 8309646 generic-all java/lang/ScopedValue/StressStackOverflow.java#no-TieredCompilation 8309646 generic-all java/lang/ScopedValue/StressStackOverflow.java#TieredStopAtLevel1 8309646 generic-all @@ -38,3 +40,24 @@ javax/management/remote/mandatory/connection/DeadLockTest.java 8309069 windows-x javax/management/remote/mandatory/connection/ConnectionTest.java 8308352 windows-x64 +########## +## Tests incompatible with virtual test thread factory. +## There is no goal to run all test with virtual test thread factory. +## So any test might be added as incompatible, the bug id is not required. + +# Incorrect stack/threadgroup/exception expectations for main thread +java/lang/StackWalker/DumpStackTest.java 0000000 generic-all +java/lang/StackWalker/StackWalkTest.java 0000000 generic-all +java/lang/StackWalker/CallerFromMain.java 0000000 generic-all +java/lang/Thread/MainThreadTest.java 0000000 generic-all +java/lang/Thread/UncaughtExceptionsTest.java 0000000 generic-all +java/lang/invoke/condy/CondyNestedResolutionTest.java 0000000 generic-all +java/lang/ref/OOMEInReferenceHandler.java 0000000 generic-all +java/util/concurrent/locks/Lock/OOMEInAQS.java 0000000 generic-all +jdk/internal/vm/Continuation/Scoped.java 0000000 generic-all + +# The problems with permissions +jdk/jfr/startupargs/TestDumpOnExit.java 0000000 generic-all +java/util/Properties/StoreReproducibilityTest.java 0000000 generic-all +javax/management/ImplementationVersion/ImplVersionTest.java 0000000 generic-all +javax/management/remote/mandatory/version/ImplVersionTest.java 0000000 generic-all diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index f95b3681723ee..c305bc0bbeb79 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -587,7 +587,6 @@ java/net/MulticastSocket/Test.java 7145658,8308807 # jdk_nio java/nio/channels/Channels/SocketChannelStreams.java 8317838 aix-ppc64 -java/nio/channels/AsyncCloseAndInterrupt.java 8368290 macosx-26.0.1 java/nio/channels/DatagramChannel/AdaptorMulticasting.java 8308807,8144003 aix-ppc64,macosx-all java/nio/channels/DatagramChannel/AfterDisconnect.java 8308807 aix-ppc64 @@ -677,6 +676,7 @@ javax/swing/AbstractButton/6711682/bug6711682.java 8060765 windows-all,macosx-al javax/swing/JFileChooser/6396844/TwentyThousandTest.java 8198003 generic-all javax/swing/JFileChooser/8194044/FileSystemRootTest.java 8327236 windows-all javax/swing/JPopupMenu/6800513/bug6800513.java 7184956 macosx-all +javax/swing/JTabbedPane/4624207/bug4624207.java 8064922 macosx-all javax/swing/SwingUtilities/TestBadBreak/TestBadBreak.java 8160720 generic-all javax/swing/JFileChooser/bug6798062.java 8146446 windows-all javax/swing/JPopupMenu/4870644/bug4870644.java 8194130 macosx-all,linux-all @@ -750,7 +750,6 @@ jdk/incubator/vector/LoadJsvmlTest.java 8305390 windows- jdk/jfr/event/compiler/TestCodeSweeper.java 8338127 generic-all jdk/jfr/event/oldobject/TestShenandoah.java 8342951 generic-all jdk/jfr/event/runtime/TestResidentSetSizeEvent.java 8309846 aix-ppc64 -jdk/jfr/jvm/TestWaste.java 8369949 generic-all ############################################################################ diff --git a/test/jdk/com/sun/java/swing/plaf/windows/MenuItem/MenuItemAcceleratorColor.java b/test/jdk/com/sun/java/swing/plaf/windows/MenuItem/MenuItemAcceleratorColor.java deleted file mode 100644 index f098be4fdbd6a..0000000000000 --- a/test/jdk/com/sun/java/swing/plaf/windows/MenuItem/MenuItemAcceleratorColor.java +++ /dev/null @@ -1,193 +0,0 @@ -/* - * 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. - */ - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; - -import javax.swing.Box; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JMenu; -import javax.swing.JMenuBar; -import javax.swing.JMenuItem; -import javax.swing.JPanel; -import javax.swing.KeyStroke; -import javax.swing.UIManager; - -import static javax.swing.BorderFactory.createEmptyBorder; - -/* - * @test id=windows - * @bug 8348760 8365375 8365389 8365625 - * @requires (os.family == "windows") - * @summary Verify that Windows Look & Feel allows changing - * accelerator colors - * @library /java/awt/regtesthelpers - * @build PassFailJFrame - * @run main/manual MenuItemAcceleratorColor - */ - -/* - * @test id=classic - * @bug 8348760 8365375 8365389 8365625 - * @requires (os.family == "windows") - * @summary Verify that Windows Classic Look & Feel allows changing - * accelerator colors - * @library /java/awt/regtesthelpers - * @build PassFailJFrame - * @run main/manual MenuItemAcceleratorColor classic - */ -public final class MenuItemAcceleratorColor { - private static final String INSTRUCTIONS = - "Click the Menu to open it.\n" + - "\n" + - "Verify that the first and the last menu items render " + - "their accelerators using the default colors, the color " + - "should match that of the menu item itself in regular and " + - "selected states.\n" + - "\n" + - "Verify that the second menu item renders its accelerator " + - "with green and that the color changes to red when selected.\n" + - "\n" + - "Verify that the third menu item renders its accelerator " + - "with magenta and yellow correspondingly.\n" + - "\n" + - "Verify that only the fifth menu item renders its accelerator " + - "with blue; both the fourth and sixth should render their " + - "accelerator with a shade of gray.\n" + - "\n" + - "If the above conditions are satisfied, press the Pass button; " + - "otherwise, press the Fail button."; - - public static void main(String[] args) throws Exception { - UIManager.setLookAndFeel((args.length > 0 && "classic".equals(args[0])) - ? "com.sun.java.swing.plaf.windows.WindowsClassicLookAndFeel" - : "com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); - - PassFailJFrame.builder() - .instructions(INSTRUCTIONS) - .rows(20) - .columns(60) - .testUI(MenuItemAcceleratorColor::createUI) - .build() - .awaitAndCheck(); - } - - private static Box createInfoPanel() { - Box box = Box.createVerticalBox(); - box.add(new JLabel("Look and Feel: " - + UIManager.getLookAndFeel() - .getName())); - box.add(new JLabel("Java version: " - + System.getProperty("java.runtime.version"))); - return box; - } - - private static JFrame createUI() { - JPanel content = new JPanel(new BorderLayout()); - content.setBorder(createEmptyBorder(8, 8, 8, 8)); - content.add(createInfoPanel(), - BorderLayout.SOUTH); - - JFrame frame = new JFrame("Accelerator colors in Windows L&F"); - frame.setJMenuBar(createMenuBar()); - frame.add(content, BorderLayout.CENTER); - frame.setSize(350, 370); - return frame; - } - - private static JMenuBar createMenuBar() { - JMenuItem first = new JMenuItem("First menu item"); - first.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F, - InputEvent.CTRL_DOWN_MASK)); - - // Modify colors for accelerator rendering - Color acceleratorForeground = UIManager.getColor("MenuItem.acceleratorForeground"); - Color acceleratorSelectionForeground = UIManager.getColor("MenuItem.acceleratorSelectionForeground"); - UIManager.put("MenuItem.acceleratorForeground", Color.GREEN); - UIManager.put("MenuItem.acceleratorSelectionForeground", Color.RED); - - JMenuItem second = new JMenuItem("Second menu item"); - second.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, - InputEvent.SHIFT_DOWN_MASK - | InputEvent.CTRL_DOWN_MASK)); - - UIManager.put("MenuItem.acceleratorForeground", Color.MAGENTA); - UIManager.put("MenuItem.acceleratorSelectionForeground", Color.YELLOW); - JMenuItem third = new JMenuItem("Third menu item"); - third.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_T, - InputEvent.ALT_DOWN_MASK)); - - // Restore colors - UIManager.put("MenuItem.acceleratorForeground", acceleratorForeground); - UIManager.put("MenuItem.acceleratorSelectionForeground", acceleratorSelectionForeground); - - - // Disabled foreground - JMenuItem fourth = new JMenuItem("Fourth menu item"); - fourth.setEnabled(false); - fourth.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F, - InputEvent.CTRL_DOWN_MASK)); - - Color disabledForeground = UIManager.getColor("MenuItem.disabledForeground"); - UIManager.put("MenuItem.disabledForeground", Color.BLUE); - - JMenuItem fifth = new JMenuItem("Fifth menu item"); - fifth.setEnabled(false); - fifth.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_F, - InputEvent.CTRL_DOWN_MASK - | InputEvent.SHIFT_DOWN_MASK)); - - // Restore disabled foreground - UIManager.put("MenuItem.disabledForeground", disabledForeground); - - JMenuItem sixth = new JMenuItem("Sixth menu item"); - sixth.setEnabled(false); - sixth.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X, - InputEvent.CTRL_DOWN_MASK - | InputEvent.ALT_DOWN_MASK)); - - - JMenuItem quit = new JMenuItem("Quit"); - quit.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_Q, - InputEvent.CTRL_DOWN_MASK)); - - JMenu menu = new JMenu("Menu"); - menu.add(first); - menu.add(second); - menu.add(third); - menu.addSeparator(); - menu.add(fourth); - menu.add(fifth); - menu.add(sixth); - menu.addSeparator(); - menu.add(quit); - - JMenuBar menuBar = new JMenuBar(); - menuBar.add(menu); - - return menuBar; - } -} diff --git a/test/jdk/com/sun/net/httpserver/ExchangeAttributeTest.java b/test/jdk/com/sun/net/httpserver/ExchangeAttributeTest.java index e7bea2814db03..2ce3dfd016d00 100644 --- a/test/jdk/com/sun/net/httpserver/ExchangeAttributeTest.java +++ b/test/jdk/com/sun/net/httpserver/ExchangeAttributeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 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,9 +27,6 @@ * @summary Tests for HttpExchange set/getAttribute * @library /test/lib * @run junit/othervm ExchangeAttributeTest - * @run junit/othervm -Djdk.httpserver.attributes=context ExchangeAttributeTest - * @run junit/othervm -Djdk.httpserver.attributes=random-string ExchangeAttributeTest - * @run junit/othervm -Djdk.httpserver.attributes ExchangeAttributeTest */ import com.sun.net.httpserver.HttpExchange; @@ -74,7 +71,7 @@ public static void setup() { public void testExchangeAttributes() throws Exception { var handler = new AttribHandler(); var server = HttpServer.create(new InetSocketAddress(LOOPBACK_ADDR,0), 10); - server.createContext("/", handler).getAttributes().put("attr", "context-val"); + server.createContext("/", handler); server.start(); try { var client = HttpClient.newBuilder().proxy(NO_PROXY).build(); @@ -104,17 +101,8 @@ static class AttribHandler implements HttpHandler { @java.lang.Override public void handle(HttpExchange exchange) throws IOException { try { - if ("context".equals(System.getProperty("jdk.httpserver.attributes"))) { - exchange.setAttribute("attr", "val"); - assertEquals("val", exchange.getAttribute("attr")); - assertEquals("val", exchange.getHttpContext().getAttributes().get("attr")); - } else { - assertNull(exchange.getAttribute("attr")); - assertEquals("context-val", exchange.getHttpContext().getAttributes().get("attr")); - exchange.setAttribute("attr", "val"); - assertEquals("val", exchange.getAttribute("attr")); - assertEquals("context-val", exchange.getHttpContext().getAttributes().get("attr")); - } + exchange.setAttribute("attr", "val"); + assertEquals("val", exchange.getAttribute("attr")); exchange.setAttribute("attr", null); assertNull(exchange.getAttribute("attr")); exchange.sendResponseHeaders(200, -1); diff --git a/test/jdk/com/sun/net/httpserver/SwitchingProtocolTest.java b/test/jdk/com/sun/net/httpserver/SwitchingProtocolTest.java new file mode 100644 index 0000000000000..ee59f1661e8d8 --- /dev/null +++ b/test/jdk/com/sun/net/httpserver/SwitchingProtocolTest.java @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2021, 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=default + * @bug 8368695 + * @summary Test 101 switching protocal response handling + * @run junit/othervm SwitchingProtocolTest + */ +/** + * @test id=preferIPv6 + * @bug 8368695 + * @summary Test 101 switching protocal response handling ipv6 + * @run junit/othervm -Djava.net.preferIPv6Addresses=true SwitchingProtocolTest + */ + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.SocketException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.logging.Level; +import java.util.logging.Logger; + +import org.junit.jupiter.api.Test; + +import com.sun.net.httpserver.HttpServer; + +public class SwitchingProtocolTest { + + private static final String RESPONSE_BODY = "Here is my reply!"; + private static final String REQUEST_BODY = "I will send all the data."; + private static final int REQUEST_LENGTH = REQUEST_BODY.getBytes().length; + private static final int msgCode = 101; + private static final String someContext = "/context"; + + static { + Logger.getLogger("").setLevel(Level.ALL); + Logger.getLogger("").getHandlers()[0].setLevel(Level.ALL); + } + + @Test + public void testSendResponse() throws Exception { + System.out.println("testSendResponse()"); + InetAddress loopback = InetAddress.getLoopbackAddress(); + HttpServer server = HttpServer.create(new InetSocketAddress(8080), 0); + HttpServer.create(new InetSocketAddress(loopback, 0), 0); + ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor(); + server.setExecutor(executor); + try { + server.createContext( + someContext, + msg -> { + byte[] reply = RESPONSE_BODY.getBytes(UTF_8); + System.err.println("Handling request: " + msg.getRequestURI()); + try { + assertEquals(-1, msg.getRequestBody().read()); + assertEquals(0, msg.getRequestBody().readAllBytes().length); + msg.sendResponseHeaders(msgCode, -1); + // Read and assert request body + byte[] requestBytes = msg.getRequestBody().readNBytes(REQUEST_LENGTH); + String requestBody = new String(requestBytes, UTF_8); + assertEquals(REQUEST_BODY, requestBody); + msg.getResponseBody().write(reply); + msg.getResponseBody().flush(); + } finally { + // don't close the exchange and don't close any stream + // to trigger the assertion. + System.err.println("Request handled: " + msg.getRequestURI()); + } + }); + server.start(); + System.out.println("Server started at port " + server.getAddress().getPort()); + + runRawSocketHttpClient(loopback, server.getAddress().getPort()); + } finally { + System.out.println("shutting server down"); + executor.shutdown(); + server.stop(0); + } + System.out.println("Server finished."); + } + + @Test + public void testCloseOutputStream() throws Exception { + System.out.println("testCloseOutputStream()"); + InetAddress loopback = InetAddress.getLoopbackAddress(); + HttpServer server = HttpServer.create(new InetSocketAddress(loopback, 0), 0); + ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor(); + server.setExecutor(executor); + try { + server.createContext( + someContext, + msg -> { + System.err.println("Handling request: " + msg.getRequestURI()); + byte[] reply = RESPONSE_BODY.getBytes(UTF_8); + try { + try { + msg.sendResponseHeaders(msgCode, -1); + msg.getResponseBody().write(reply); + msg.getResponseBody().flush(); + // Read and assert request body + byte[] requestBytes = msg.getRequestBody().readNBytes(REQUEST_LENGTH); + String requestBody = new String(requestBytes, UTF_8); + assertEquals(REQUEST_BODY, requestBody); + msg.getResponseBody().close(); + Thread.sleep(50); + } catch (IOException | InterruptedException ie) { + ie.printStackTrace(); + } + } finally { + System.err.println("Request handled: " + msg.getRequestURI()); + } + }); + server.start(); + System.out.println("Server started at port " + server.getAddress().getPort()); + + runRawSocketHttpClient(loopback, server.getAddress().getPort()); + } finally { + System.out.println("shutting server down"); + executor.shutdown(); + server.stop(0); + } + System.out.println("Server finished."); + } + + + @Test + public void testException() throws Exception { + System.out.println("testException()"); + InetAddress loopback = InetAddress.getLoopbackAddress(); + HttpServer server = HttpServer.create(new InetSocketAddress(loopback, 0), 0); + ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor(); + server.setExecutor(executor); + try { + server.createContext( + someContext, + msg -> { + msg.sendResponseHeaders(msgCode, -1); + throw new RuntimeException("Simulated exception"); + }); + server.start(); + System.out.println("Server started at port " + server.getAddress().getPort()); + + runRawSocketHttpClient(loopback, server.getAddress().getPort(), true); + } finally { + System.out.println("shutting server down"); + executor.shutdown(); + server.stop(0); + } + System.out.println("Server finished."); + } + + static void runRawSocketHttpClient(InetAddress address, int port) throws Exception { + runRawSocketHttpClient(address, port, false); + } + + static void runRawSocketHttpClient(InetAddress address, int port, boolean exception) + throws Exception { + Socket socket = null; + PrintWriter writer = null; + BufferedReader reader = null; + final String CRLF = "\r\n"; + try { + socket = new Socket(address, port); + writer = new PrintWriter(new OutputStreamWriter(socket.getOutputStream())); + System.out.println("Client connected by socket: " + socket); + String body = REQUEST_BODY; + var contentLength = body.getBytes(UTF_8).length; + + writer.print("GET " + someContext + "/ HTTP/1.1" + CRLF); + writer.print("User-Agent: Java/" + System.getProperty("java.version") + CRLF); + writer.print("Host: " + address.getHostName() + CRLF); + writer.print("Accept: */*" + CRLF); + writer.print("Content-Length: " + contentLength + CRLF); + writer.print("Connection: keep-alive" + CRLF); + writer.print("Connection: Upgrade" + CRLF); + writer.print("Upgrade: custom" + CRLF); + writer.print(CRLF); // Important, else the server will expect that + // there's more into the request. + writer.flush(); + System.out.println("Client wrote request to socket: " + socket); + + System.out.println("Client wrote body to socket: " + socket); + + reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); + System.out.println("Client start reading from server:"); + String line = reader.readLine(); + StringBuilder responseBody = new StringBuilder(); + for (; line != null; line = reader.readLine()) { + if (line.isEmpty()) { + break; + } + System.out.println("\"" + line + "\""); + } + // Write request body after headers + writer.print(body); + writer.flush(); + // Read response body + char[] buf = new char[RESPONSE_BODY.length()]; + int read = reader.read(buf); + if (read > 0) { + responseBody.append(buf, 0, read); + } + String actualResponse = responseBody.toString(); + assertEquals(RESPONSE_BODY, actualResponse, "Response body does not match"); + System.out.println("Client finished reading from server"); + } catch (SocketException se) { + if (!exception) { + fail("Unexpected exception: " + se); + } + assertEquals("Connection reset", se.getMessage()); + } finally { + if (writer != null) { + writer.close(); + } + if (reader != null) + try { + reader.close(); + } catch (IOException logOrIgnore) { + logOrIgnore.printStackTrace(); + } + if (socket != null) { + try { + socket.close(); + } catch (IOException logOrIgnore) { + logOrIgnore.printStackTrace(); + } + } + } + System.out.println("Client finished."); + } +} diff --git a/test/jdk/java/awt/PrintJob/GetGraphicsTest.java b/test/jdk/java/awt/PrintJob/GetGraphicsTest.java index 2fe82e57c5abc..61abe37b66b12 100644 --- a/test/jdk/java/awt/PrintJob/GetGraphicsTest.java +++ b/test/jdk/java/awt/PrintJob/GetGraphicsTest.java @@ -23,7 +23,7 @@ /* @test - @bug 5051056 8367702 + @bug 50510568367702 @key headful printer @summary PrintJob.getGraphics() should return null after PrintJob.end() is called. @run main GetGraphicsTest diff --git a/test/jdk/java/awt/Toolkit/ScreenInsetsTest/ScreenInsetsTest.java b/test/jdk/java/awt/Toolkit/ScreenInsetsTest/ScreenInsetsTest.java index 207954c521b65..2cd05b08fc518 100644 --- a/test/jdk/java/awt/Toolkit/ScreenInsetsTest/ScreenInsetsTest.java +++ b/test/jdk/java/awt/Toolkit/ScreenInsetsTest/ScreenInsetsTest.java @@ -24,7 +24,7 @@ /* * @test * @key headful - * @bug 8020443 6899304 4737732 8357390 + * @bug 8020443 6899304 4737732 * @summary Tests that Toolkit.getScreenInsets() returns correct insets * @library /test/lib * @build jdk.test.lib.Platform @@ -44,7 +44,7 @@ public class ScreenInsetsTest { private static final int SIZE = 100; // Allow a margin tolerance of 1 pixel due to scaling - private static final int MARGIN_TOLERANCE = 2; + private static final int MARGIN_TOLERANCE = 1; public static void main(String[] args) throws InterruptedException { GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); diff --git a/test/jdk/java/awt/color/ICC_Profile/SerializedFormSize.java b/test/jdk/java/awt/color/ICC_Profile/SerializedFormSize.java deleted file mode 100644 index bb8d7a0ab88e5..0000000000000 --- a/test/jdk/java/awt/color/ICC_Profile/SerializedFormSize.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * 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.color.ColorSpace; -import java.awt.color.ICC_Profile; -import java.io.ByteArrayOutputStream; -import java.io.ObjectOutputStream; - -/** - * @test - * @bug 8369032 - * @summary Checks the size of the serialized ICC_Profile for standard and - * non-standard profiles. - */ -public final class SerializedFormSize { - - private static final ICC_Profile[] PROFILES = { - ICC_Profile.getInstance(ColorSpace.CS_sRGB), - ICC_Profile.getInstance(ColorSpace.CS_LINEAR_RGB), - ICC_Profile.getInstance(ColorSpace.CS_CIEXYZ), - ICC_Profile.getInstance(ColorSpace.CS_PYCC), - ICC_Profile.getInstance(ColorSpace.CS_GRAY) - }; - - public static void main(String[] args) throws Exception { - for (ICC_Profile profile : PROFILES) { - byte[] data = profile.getData(); - int dataSize = data.length; - int min = 3; // At least version, name and data fields - int max = 200; // Small enough to confirm no data saved - - // Standard profile: should serialize to a small size, no data - test(profile, min, max); - // Non-standard profile: includes full data, but only once - test(ICC_Profile.getInstance(data), dataSize, dataSize + max); - } - } - - private static void test(ICC_Profile p, int min, int max) throws Exception { - try (var bos = new ByteArrayOutputStream(); - var oos = new ObjectOutputStream(bos)) - { - oos.writeObject(p); - int size = bos.size(); - if (size < min || size > max) { - System.err.println("Expected: >= " + min + " and <= " + max); - System.err.println("Actual: " + size); - throw new RuntimeException("Wrong size"); - } - } - } -} diff --git a/test/jdk/java/awt/font/NumericShaper/NSEqualsTest.java b/test/jdk/java/awt/font/NumericShaper/NSEqualsTest.java deleted file mode 100644 index 6af73b7efa2ff..0000000000000 --- a/test/jdk/java/awt/font/NumericShaper/NSEqualsTest.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 8365077 - * @summary confirm that an instance which is created with Enum ranges is - * equal to another instance which is created with equivalent traditional - * ranges, and that in such a case the hashCodes are also equal. - */ - -import java.awt.font.NumericShaper; -import java.awt.font.NumericShaper.Range; -import static java.awt.font.NumericShaper.Range.*; -import java.util.EnumSet; - -public class NSEqualsTest { - - public static void main(String[] args) { - - for (Range r1 : Range.values()) { - test(r1); - for (Range r2 : Range.values()) { - test(r1, r2); - } - } - } - - static void test(Range r) { - if (r.ordinal() > MONGOLIAN.ordinal()) { - return; - } - int o = 1 << r.ordinal(); - NumericShaper nsr = NumericShaper.getContextualShaper(EnumSet.of(r)); - NumericShaper nso = NumericShaper.getContextualShaper(o); - printAndCompare(nsr, nso); - } - - static void test(Range r1, Range r2) { - if (r1.ordinal() > MONGOLIAN.ordinal() || r2.ordinal() > MONGOLIAN.ordinal()) { - return; - } - int o1 = 1 << r1.ordinal(); - int o2 = 1 << r2.ordinal(); - - NumericShaper nsr = NumericShaper.getContextualShaper(EnumSet.of(r1, r2)); - NumericShaper nso = NumericShaper.getContextualShaper(o1 | o2); - printAndCompare(nsr, nso); - } - - static void printAndCompare(NumericShaper nsr, NumericShaper nso) { - System.err.println(nsr); - System.err.println(nso); - System.err.println(nsr.hashCode() + " vs " + nso.hashCode() + - " equal: " + nsr.equals(nso)); - if (!nsr.equals(nso)) { - throw new RuntimeException("Expected equal"); - } - if (nsr.hashCode() != nso.hashCode()) { - throw new RuntimeException("Different hash codes:"); - } - } -} - diff --git a/test/jdk/java/awt/image/BandedSampleModel/BSMCreateCompatibleSMTest.java b/test/jdk/java/awt/image/BandedSampleModel/BSMCreateCompatibleSMTest.java deleted file mode 100644 index a47659300e82f..0000000000000 --- a/test/jdk/java/awt/image/BandedSampleModel/BSMCreateCompatibleSMTest.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @bug 6453640 - * @summary Verify BandedSampleModel.createCompatibleSampleModel - * and createSubsetSampleModel behaviour - * @run main BSMCreateCompatibleSMTest - */ - -import java.awt.image.BandedSampleModel; -import java.awt.image.DataBuffer; -import java.awt.image.RasterFormatException; - -public class BSMCreateCompatibleSMTest { - - public static void main(String[] args) { - - // These should all be OK - BandedSampleModel bsm = new BandedSampleModel(DataBuffer.TYPE_BYTE, 1, 1, 1); - bsm.createCompatibleSampleModel(20_000, 20_000); - int[] bands = { 0 } ; - bsm.createSubsetSampleModel(bands); - - // These should all throw an exception - try { - bsm.createCompatibleSampleModel(-1, 1); - throw new RuntimeException("No exception for illegal w"); - } catch (IllegalArgumentException e) { - System.out.println(e); - } - - try { - bsm.createCompatibleSampleModel(1, 0); - throw new RuntimeException("No exception for illegal h"); - } catch (IllegalArgumentException e) { - System.out.println(e); - } - - try { - bsm.createCompatibleSampleModel(-1, -1); - throw new RuntimeException("No exception for illegal w+h"); - } catch (IllegalArgumentException e) { - System.out.println(e); - } - - try { - bsm.createCompatibleSampleModel(50_000, 50_000); - throw new RuntimeException("No exception for too large dims"); - } catch (IllegalArgumentException e) { - System.out.println(e); - } - - try { - int[] bands0 = { } ; - bsm.createSubsetSampleModel(bands0); - throw new RuntimeException("No exception for empty bands[]"); - } catch (IllegalArgumentException e) { - System.out.println(e); - } - - try { - int[] bands1 = { 1 } ; - bsm.createSubsetSampleModel(bands1); - throw new RuntimeException("No exception for out of bounds band"); - } catch (ArrayIndexOutOfBoundsException e) { - System.out.println(e); - } - - try { - int[] bands2 = { 0, 0 } ; - bsm.createSubsetSampleModel(bands2); - throw new RuntimeException("No exception for too many bands"); - } catch (RasterFormatException e) { - System.out.println(e); - } - } - -} diff --git a/test/jdk/java/awt/print/PrinterJob/PageRanges.java b/test/jdk/java/awt/print/PrinterJob/PageRanges.java index e80330bae6ceb..accde99ae9565 100644 --- a/test/jdk/java/awt/print/PrinterJob/PageRanges.java +++ b/test/jdk/java/awt/print/PrinterJob/PageRanges.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -21,63 +21,58 @@ * questions. */ -/* +/** * @test * @bug 6575331 * @key printer * @summary The specified pages should be printed. - * @library /java/awt/regtesthelpers - * @library /test/lib - * @build PassFailJFrame - * @build jtreg.SkippedException - * @run main/manual PageRanges + * @run main/manual=yesno PageRanges */ -import java.awt.Graphics; -import java.awt.print.PageFormat; -import java.awt.print.Printable; -import java.awt.print.PrinterException; -import java.awt.print.PrinterJob; -import jtreg.SkippedException; +import java.awt.*; +import java.awt.print.*; public class PageRanges implements Printable { - private static final String INSTRUCTIONS = """ - This test prints two jobs and tests that the specified range - of pages is printed. - In the first dialog, select a page range of 2 to 3, and press OK. - In the second dialog, select ALL, to print all pages (in total 5 pages). - Collect the two print outs and confirm the jobs are printed correctly. - """; + + static String[] instr = { + "This test prints two jobs, and tests that the specified range", + "of pages is printed. You must have a printer installed for this test.", + "In the first dialog, select a page range of 2 to 3, and press OK", + "In the second dialog, select ALL, to print all pages (in total 5 pages).", + "Collect the two print outs and confirm the jobs printed correctly", + }; public static void main(String args[]) throws Exception { + for (int i=0;i= 5) { return NO_SUCH_PAGE; } g.drawString("Page : " + (pi+1), 200, 200); + return PAGE_EXISTS; } } diff --git a/test/jdk/java/awt/print/PrinterJob/PolylinePrintingTest.java b/test/jdk/java/awt/print/PrinterJob/PolylinePrintingTest.java index c9dcdfdd450f1..7d8568c01f98c 100644 --- a/test/jdk/java/awt/print/PrinterJob/PolylinePrintingTest.java +++ b/test/jdk/java/awt/print/PrinterJob/PolylinePrintingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 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 @@ -21,56 +21,31 @@ * questions. */ -/* - * @test +/** * @bug 8041902 * @key printer * @summary Test printing of wide poly lines. - * @library /java/awt/regtesthelpers - * @library /test/lib - * @build PassFailJFrame - * @build jtreg.SkippedException - * @run main/manual PolylinePrintingTest + * @run main/manual=yesno PolylinePrintingTest */ +import java.awt.Dialog; +import java.awt.Frame; +import java.awt.TextArea; import java.awt.BasicStroke; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.geom.Path2D; import java.awt.print.PageFormat; +import java.awt.print.Paper; import java.awt.print.Printable; import java.awt.print.PrinterException; import java.awt.print.PrinterJob; -import jtreg.SkippedException; public class PolylinePrintingTest implements Printable { - private static final String INSTRUCTIONS = """ - Press OK in the print dialog and collect the printed page. - Passing test : Output should show two identical chevrons. - Failing test : The line joins will appear different. - """; - - public static void main(String[] args) throws Exception { - PrinterJob job = PrinterJob.getPrinterJob(); - if (job.getPrintService() == null) { - throw new SkippedException("Printer not configured or available."); - } - - PassFailJFrame passFailJFrame = PassFailJFrame.builder() - .instructions(INSTRUCTIONS) - .columns(45) - .build(); - - job.setPrintable(new PolylinePrintingTest()); - if (job.printDialog()) { - job.print(); - } - - passFailJFrame.awaitAndCheck(); - } public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException { + if (pageIndex > 0) { return NO_SUCH_PAGE; } @@ -91,6 +66,7 @@ public int print(Graphics graphics, PageFormat pageFormat, private void drawPolylineGOOD(Graphics2D g2d, int[] x2Points, int[] y2Points) { + Path2D polyline = new Path2D.Float(Path2D.WIND_EVEN_ODD, x2Points.length); @@ -107,4 +83,141 @@ private void drawPolylineBAD(Graphics2D g, int[] xp, int[] yp) { g.translate(0, offset); g.drawPolyline(xp, yp, xp.length); } + + public PolylinePrintingTest() throws PrinterException { + PrinterJob job = PrinterJob.getPrinterJob(); + PageFormat pf = job.defaultPage(); + Paper p = pf.getPaper(); + p.setImageableArea(0,0,p.getWidth(), p.getHeight()); + pf.setPaper(p); + job.setPrintable(this, pf); + if (job.printDialog()) { + job.print(); + } + } + + public static void main(String[] args) throws PrinterException { + String[] instructions = { + "You must have a printer available to perform this test.", + "OK the print dialog, and collect the printed page.", + "Passing test : Output should show two identical chevrons.", + "Failing test : The line joins will appear different." + }; + Sysout.createDialog(); + Sysout.printInstructions(instructions); + new PolylinePrintingTest(); + } } + +class Sysout { + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.show(); + println( "Any messages for the tester will display here." ); + } + + public static void createDialog( ) + { + dialog = new TestDialog( new 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 ); + } + +}// Sysout class + +/** + 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 { + TextArea instructionsText; + TextArea messageText; + int maxStringLength = 80; + + //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); + + pack(); + + show(); + }// TestDialog() + + //DO NOT call this directly, go through Sysout + public void printInstructions( String[] instructions ) + { + //Clear out any current instructions + instructionsText.setText( "" ); + + //Go down array of instruction strings + + String printStr, remainingStr; + for( int i=0; i < instructions.length; i++ ) + { + //chop up each into pieces maxSringLength long + remainingStr = instructions[ i ]; + while( remainingStr.length() > 0 ) + { + //if longer than max then chop off first max chars to print + if( remainingStr.length() >= maxStringLength ) + { + //Try to chop on a word boundary + int posOfSpace = remainingStr. + lastIndexOf( ' ', maxStringLength - 1 ); + if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; + + printStr = remainingStr.substring( 0, posOfSpace + 1 ); + remainingStr = remainingStr.substring( posOfSpace + 1 ); + } + //else just print + else + { + printStr = remainingStr; + remainingStr = ""; + } + + instructionsText.append( printStr + "\n" ); + + }// while + + }// for + + }//printInstructions() + + //DO NOT call this directly, go through Sysout + public void displayMessage( String messageIn ) + { + messageText.append( messageIn + "\n" ); + } + +}// TestDialog class + diff --git a/test/jdk/java/awt/print/PrinterJob/SwingUIText.java b/test/jdk/java/awt/print/PrinterJob/SwingUIText.java index 6ef5064fc306b..5fcd5e391581a 100644 --- a/test/jdk/java/awt/print/PrinterJob/SwingUIText.java +++ b/test/jdk/java/awt/print/PrinterJob/SwingUIText.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -21,70 +21,44 @@ * questions. */ -/* +/** * @test * @bug 6488219 6560738 7158350 8017469 * @key printer * @summary Test that text printed in Swing UI measures and looks OK. - * @library /java/awt/regtesthelpers /test/lib - * @build PassFailJFrame jtreg.SkippedException - * @run main/manual SwingUIText + * @run main/manual=yesno PrintTextTest */ -import java.awt.Font; -import java.awt.Graphics; -import java.awt.GridLayout; -import java.awt.print.PageFormat; -import java.awt.print.Printable; -import java.awt.print.PrinterJob; -import javax.swing.JButton; -import javax.swing.JEditorPane; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JTextArea; -import javax.swing.JTextField; -import jtreg.SkippedException; +import java.awt.*; +import javax.swing.*; +import java.awt.print.*; public class SwingUIText implements Printable { - private static JFrame frame; - private static final String INSTRUCTIONS = """ - This test checks that when a Swing UI is printed, - the text in each component aligns with the component’s length as seen on-screen. - It also ensures the text spacing is reasonably even, though this is subjective. - The comparison should be made with JDK 1.5 GA or JDK 1.6 GA. - - Steps: - 1. Press the "Print" or "OK" button on the Print dialog. - This will print the content of the "Swing UI Text Printing Test" JFrame. - 2. Compare the printout with the content of the JFrame. - 3. If they match, press Pass; otherwise, press Fail. - """; - - public static void main(String args[]) throws Exception { - PrinterJob job = PrinterJob.getPrinterJob(); - if (job.getPrintService() == null) { - throw new SkippedException("Printer not configured or available."); - } - PassFailJFrame passFailJFrame = PassFailJFrame.builder() - .instructions(INSTRUCTIONS) - .columns(45) - .testUI(SwingUIText::createTestUI) - .build(); + static String[] instructions = { + "This tests that when a Swing UI is printed, that the text", + "in each component properly matches the length of the component", + "as seen on-screen, and that the spacing of the text is of", + "reasonable even-ness. This latter part is very subjective and", + "the comparison has to be with JDK1.5 GA, or JDK 1.6 GA", + }; - job.setPrintable(new SwingUIText()); - if (job.printDialog()) { - job.print(); - } + static JFrame frame; - passFailJFrame.awaitAndCheck(); + public static void main(String args[]) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + createUI(); + } + }); } - public static JFrame createTestUI() { - frame = new JFrame(); + public static void createUI() { + + Sysout.createDialogWithInstructions(instructions); + JPanel panel = new JPanel(); - panel.setLayout(new GridLayout(4, 1)); + panel.setLayout(new GridLayout(4,1)); String text = "marvelous suspicious solving"; displayText(panel, text); @@ -115,12 +89,24 @@ public static JFrame createTestUI() { frame = new JFrame("Swing UI Text Printing Test"); frame.getContentPane().add(panel); frame.pack(); - return frame; + frame.setVisible(true); + + PrinterJob job = PrinterJob.getPrinterJob(); + PageFormat pf = job.defaultPage(); + job.setPrintable(new SwingUIText(), pf); + if (job.printDialog()) { + try { job.print(); } + catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + } } + static void displayText(JPanel p, String text) { JPanel panel = new JPanel(); - panel.setLayout(new GridLayout(2, 1)); + panel.setLayout(new GridLayout(2,1)); JPanel row = new JPanel(); Font font = new Font("Dialog", Font.PLAIN, 12); @@ -128,7 +114,7 @@ static void displayText(JPanel p, String text) { label.setFont(font); row.add(label); - JButton button = new JButton("Print " + text); + JButton button = new JButton("Print "+text); button.setMnemonic('P'); button.setFont(font); row.add(button); @@ -147,14 +133,132 @@ static void displayText(JPanel p, String text) { p.add(panel); } - public int print(Graphics g, PageFormat pf, int pageIndex) { + public int print(Graphics g, PageFormat pf, int pageIndex) + throws PrinterException { + if (pageIndex >= 1) { return Printable.NO_SUCH_PAGE; } - g.translate((int)pf.getImageableX(), (int)pf.getImageableY()); frame.printAll(g); + return Printable.PAGE_EXISTS; } } + +class Sysout + { + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.show(); + println( "Any messages for the tester will display here." ); + } + + public static void createDialog( ) + { + dialog = new TestDialog( new 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 ); + } + + }// Sysout class + +/** + 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 + { + + TextArea instructionsText; + TextArea messageText; + int maxStringLength = 80; + + //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( "", 10, maxStringLength, scrollBoth ); + add( "North", instructionsText ); + + messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); + add("South", messageText); + + pack(); + + show(); + }// TestDialog() + + //DO NOT call this directly, go through Sysout + public void printInstructions( String[] instructions ) + { + //Clear out any current instructions + instructionsText.setText( "" ); + + //Go down array of instruction strings + + String printStr, remainingStr; + for( int i=0; i < instructions.length; i++ ) + { + //chop up each into pieces maxSringLength long + remainingStr = instructions[ i ]; + while( remainingStr.length() > 0 ) + { + //if longer than max then chop off first max chars to print + if( remainingStr.length() >= maxStringLength ) + { + //Try to chop on a word boundary + int posOfSpace = remainingStr. + lastIndexOf( ' ', maxStringLength - 1 ); + + if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; + + printStr = remainingStr.substring( 0, posOfSpace + 1 ); + remainingStr = remainingStr.substring( posOfSpace + 1 ); + } + //else just print + else + { + printStr = remainingStr; + remainingStr = ""; + } + + instructionsText.append( printStr + "\n" ); + + }// while + + }// for + + }//printInstructions() + + //DO NOT call this directly, go through Sysout + public void displayMessage( String messageIn ) + { + messageText.append( messageIn + "\n" ); + } + +}// TestDialog class diff --git a/test/jdk/java/io/ByteArrayOutputStream/WriteToReleasesCarrier.java b/test/jdk/java/io/ByteArrayOutputStream/WriteToReleasesCarrier.java index a0c13f24c7c9e..c0607fd94946e 100644 --- a/test/jdk/java/io/ByteArrayOutputStream/WriteToReleasesCarrier.java +++ b/test/jdk/java/io/ByteArrayOutputStream/WriteToReleasesCarrier.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,6 @@ * @summary Test ByteArrayOutputStream.writeTo releases carrier thread * @requires vm.continuations * @modules java.base/java.lang:+open - * @library /test/lib * @run main WriteToReleasesCarrier */ @@ -35,14 +34,14 @@ import java.io.IOException; import java.io.OutputStream; import java.nio.charset.StandardCharsets; +import java.lang.reflect.Constructor; import java.util.Arrays; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; import java.util.concurrent.Executor; import java.util.concurrent.Executors; -import java.util.concurrent.ExecutorService; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.LockSupport; -import jdk.test.lib.thread.VThreadScheduler; public class WriteToReleasesCarrier { public static void main(String[] args) throws Exception { @@ -54,7 +53,7 @@ public static void main(String[] args) throws Exception { var target = new ParkingOutputStream(); try (ExecutorService scheduler = Executors.newFixedThreadPool(1)) { - Thread.Builder builder = VThreadScheduler.virtualThreadBuilder(scheduler); + Thread.Builder builder = virtualThreadBuilder(scheduler); var started = new CountDownLatch(1); var vthread1 = builder.start(() -> { started.countDown(); @@ -119,4 +118,14 @@ byte[] toByteArray() { return baos.toByteArray(); } } + + /** + * Returns a builder to create virtual threads that use the given scheduler. + */ + static Thread.Builder.OfVirtual virtualThreadBuilder(Executor scheduler) throws Exception { + Class clazz = Class.forName("java.lang.ThreadBuilders$VirtualThreadBuilder"); + Constructor ctor = clazz.getDeclaredConstructor(Executor.class); + ctor.setAccessible(true); + return (Thread.Builder.OfVirtual) ctor.newInstance(scheduler); + } } diff --git a/test/jdk/java/io/Serializable/cloneArray/CloneArray.java b/test/jdk/java/io/Serializable/cloneArray/CloneArray.java index 0a427e29da578..a8de4407912bf 100644 --- a/test/jdk/java/io/Serializable/cloneArray/CloneArray.java +++ b/test/jdk/java/io/Serializable/cloneArray/CloneArray.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -25,6 +25,7 @@ /* @test * @bug 6990094 * @summary Verify ObjectInputStream.cloneArray works on many kinds of arrays + * @author Stuart Marks, Joseph D. Darcy */ import java.io.ByteArrayInputStream; diff --git a/test/jdk/java/lang/Byte/Decode.java b/test/jdk/java/lang/Byte/Decode.java index 590c35989f7e9..b4ef798cb7e44 100644 --- a/test/jdk/java/lang/Byte/Decode.java +++ b/test/jdk/java/lang/Byte/Decode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ * @test * @bug 4242173 5017980 6576055 * @summary Test Byte.decode method + * @author madbot + * @author Joseph D. Darcy */ /** diff --git a/test/jdk/java/lang/Class/IsAnnotationType.java b/test/jdk/java/lang/Class/IsAnnotationType.java index e007201d95c69..2189e1c571520 100644 --- a/test/jdk/java/lang/Class/IsAnnotationType.java +++ b/test/jdk/java/lang/Class/IsAnnotationType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 4891872 4988155 * @summary Check isAnnotation() method + * @author Joseph D. Darcy */ import java.lang.annotation.*; diff --git a/test/jdk/java/lang/Class/IsEnum.java b/test/jdk/java/lang/Class/IsEnum.java index 3d2d9103ddb93..fc0b0f7632b01 100644 --- a/test/jdk/java/lang/Class/IsEnum.java +++ b/test/jdk/java/lang/Class/IsEnum.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 4891872 4989735 4990789 5020490 * @summary Check isEnum() method + * @author Joseph D. Darcy */ import java.lang.annotation.*; diff --git a/test/jdk/java/lang/Class/IsSynthetic.java b/test/jdk/java/lang/Class/IsSynthetic.java index 1775b6bc11d34..d594f6303e1b7 100644 --- a/test/jdk/java/lang/Class/IsSynthetic.java +++ b/test/jdk/java/lang/Class/IsSynthetic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 5012133 * @summary Check Class.isSynthetic method + * @author Joseph D. Darcy */ import java.lang.reflect.*; diff --git a/test/jdk/java/lang/Class/getEnclosingConstructor/EnclosingConstructorTests.java b/test/jdk/java/lang/Class/getEnclosingConstructor/EnclosingConstructorTests.java index c08f33af1e67a..ca128021e0cd8 100644 --- a/test/jdk/java/lang/Class/getEnclosingConstructor/EnclosingConstructorTests.java +++ b/test/jdk/java/lang/Class/getEnclosingConstructor/EnclosingConstructorTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 4962341 6832557 * @summary Check getEnclosingMethod method + * @author Joseph D. Darcy */ import java.lang.reflect.Constructor; diff --git a/test/jdk/java/lang/Class/getEnclosingMethod/EnclosingMethodTests.java b/test/jdk/java/lang/Class/getEnclosingMethod/EnclosingMethodTests.java index e890bb75d1ebb..3a2a0910fc72a 100644 --- a/test/jdk/java/lang/Class/getEnclosingMethod/EnclosingMethodTests.java +++ b/test/jdk/java/lang/Class/getEnclosingMethod/EnclosingMethodTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 4962341 * @summary Check getEnclosingMethod method + * @author Joseph D. Darcy */ import java.lang.reflect.Method; diff --git a/test/jdk/java/lang/Double/BitwiseConversion.java b/test/jdk/java/lang/Double/BitwiseConversion.java index 06e15d9557502..381a7e9aed639 100644 --- a/test/jdk/java/lang/Double/BitwiseConversion.java +++ b/test/jdk/java/lang/Double/BitwiseConversion.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ * @library ../Math * @build DoubleConsts * @run main BitwiseConversion + * @author Joseph D. Darcy */ import static java.lang.Double.*; diff --git a/test/jdk/java/lang/Double/Constants.java b/test/jdk/java/lang/Double/Constants.java index e7aa5cbceb90b..676630e12b96c 100644 --- a/test/jdk/java/lang/Double/Constants.java +++ b/test/jdk/java/lang/Double/Constants.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2005, 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,7 @@ * @compile Constants.java * @bug 4397405 4826652 * @summary Testing constant-ness of Double.{MIN_VALUE, MAX_VALUE}, etc. + * @author Joseph D. Darcy */ public class Constants { diff --git a/test/jdk/java/lang/Double/Extrema.java b/test/jdk/java/lang/Double/Extrema.java index db9a10fb279c7..fef17100e0afd 100644 --- a/test/jdk/java/lang/Double/Extrema.java +++ b/test/jdk/java/lang/Double/Extrema.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 4408489 4826652 * @summary Testing values of Double.{MIN_VALUE, MIN_NORMAL, MAX_VALUE} + * @author Joseph D. Darcy */ public class Extrema { diff --git a/test/jdk/java/lang/Double/NaNInfinityParsing.java b/test/jdk/java/lang/Double/NaNInfinityParsing.java index 8b5d0e4888fbb..846dcecd3b9f4 100644 --- a/test/jdk/java/lang/Double/NaNInfinityParsing.java +++ b/test/jdk/java/lang/Double/NaNInfinityParsing.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 4428772 * @summary Testing recognition of "NaN" and "Infinity" strings + * @author Joseph D. Darcy */ diff --git a/test/jdk/java/lang/Double/ParseHexFloatingPoint.java b/test/jdk/java/lang/Double/ParseHexFloatingPoint.java index 60fa13df75b14..a26a8b7a756b8 100644 --- a/test/jdk/java/lang/Double/ParseHexFloatingPoint.java +++ b/test/jdk/java/lang/Double/ParseHexFloatingPoint.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2017, 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 @@ * @run main ParseHexFloatingPoint * @bug 4826774 8078672 * @summary Numerical tests for hexadecimal inputs to parse{Double, Float} (use -Dseed=X to set PRNG seed) + * @author Joseph D. Darcy * @key randomness */ diff --git a/test/jdk/java/lang/Double/ToHexString.java b/test/jdk/java/lang/Double/ToHexString.java index c408f74fa636c..a9f07bba50840 100644 --- a/test/jdk/java/lang/Double/ToHexString.java +++ b/test/jdk/java/lang/Double/ToHexString.java @@ -1,6 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2025, Alibaba Group Holding Limited. All Rights Reserved. + * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +28,7 @@ * @library ../Math * @build DoubleConsts * @run main ToHexString + * @author Joseph D. Darcy */ import java.util.regex.*; @@ -175,26 +175,6 @@ public static int toHexStringTests() { {"+4.9e-324", "0000000000000001"}, {"-4.9e-324", "8000000000000001"}, - // Test cases for trailing zeros in significand - // These test the removal of trailing zeros in the hexadecimal representation - // The comments indicate the number of trailing zeros removed from the significand - // For "0x1.0p1", there are 13 trailing zeros in the significand, but only 12 are removed - // as we always keep at least one hex digit in the significand - {"0x1.0p1", "4000000000000000"}, // 12 trailing zeros removed (13 total, but only 12 removed) - {"0x1.1p1", "4001000000000000"}, // 12 trailing zeros removed (all zeros after '1') - {"0x1.01p1", "4000100000000000"}, // 11 trailing zeros removed - {"0x1.001p1", "4000010000000000"}, // 10 trailing zeros removed - {"0x1.0001p1", "4000001000000000"}, // 9 trailing zeros removed - {"0x1.00001p1", "4000000100000000"}, // 8 trailing zeros removed - {"0x1.000001p1", "4000000010000000"}, // 7 trailing zeros removed - {"0x1.0000001p1", "4000000001000000"}, // 6 trailing zeros removed - {"0x1.00000001p1", "4000000000100000"}, // 5 trailing zeros removed - {"0x1.000000001p1", "4000000000010000"}, // 4 trailing zeros removed - {"0x1.0000000001p1", "4000000000001000"}, // 3 trailing zeros removed - {"0x1.00000000001p1", "4000000000000100"}, // 2 trailing zeros removed - {"0x1.000000000001p1", "4000000000000010"}, // 1 trailing zero removed (minimum) - {"0x1.0000000000001p1", "4000000000000001"}, // 0 trailing zeros removed (no trailing zeros to remove) - // fdlibm k_sin.c {"+5.00000000000000000000e-01", "3FE0000000000000"}, {"-1.66666666666666324348e-01", "BFC5555555555549"}, diff --git a/test/jdk/java/lang/Float/BitwiseConversion.java b/test/jdk/java/lang/Float/BitwiseConversion.java index 9bb4a34a55b3d..973e00e7008cf 100644 --- a/test/jdk/java/lang/Float/BitwiseConversion.java +++ b/test/jdk/java/lang/Float/BitwiseConversion.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ * @library ../Math * @build FloatConsts * @run main BitwiseConversion + * @author Joseph D. Darcy */ import static java.lang.Float.*; diff --git a/test/jdk/java/lang/Float/Constants.java b/test/jdk/java/lang/Float/Constants.java index 47463fc59166c..b6ad85ca0c256 100644 --- a/test/jdk/java/lang/Float/Constants.java +++ b/test/jdk/java/lang/Float/Constants.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2005, 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,7 @@ * @compile Constants.java * @bug 4397405 4826652 * @summary Testing constant-ness of Float.{MIN_VALUE, MAX_VALUE}, etc. + * @author Joseph D. Darcy */ public class Constants { diff --git a/test/jdk/java/lang/Float/Extrema.java b/test/jdk/java/lang/Float/Extrema.java index 46447bfcb2f39..869f22072e7ed 100644 --- a/test/jdk/java/lang/Float/Extrema.java +++ b/test/jdk/java/lang/Float/Extrema.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 4408489 4826652 * @summary Testing values of Float.{MIN_VALUE, MIN_NORMAL, MAX_VALUE} + * @author Joseph D. Darcy */ public class Extrema { diff --git a/test/jdk/java/lang/Float/NaNInfinityParsing.java b/test/jdk/java/lang/Float/NaNInfinityParsing.java index 6df42b376a52d..38a402a97752f 100644 --- a/test/jdk/java/lang/Float/NaNInfinityParsing.java +++ b/test/jdk/java/lang/Float/NaNInfinityParsing.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 4428772 * @summary Testing recognition of "NaN" and "Infinity" strings + * @author Joseph D. Darcy */ diff --git a/test/jdk/java/lang/Integer/Decode.java b/test/jdk/java/lang/Integer/Decode.java index b5f881a0e9f5b..42493221fe42a 100644 --- a/test/jdk/java/lang/Integer/Decode.java +++ b/test/jdk/java/lang/Integer/Decode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ * @test * @bug 4136371 5017980 6576055 * @summary Test Integer.decode method + * @author madbot + * @author Joseph D. Darcy */ /** diff --git a/test/jdk/java/lang/Integer/ParsingTest.java b/test/jdk/java/lang/Integer/ParsingTest.java index 24e1dd6f3aa53..f5f64f70c84f8 100644 --- a/test/jdk/java/lang/Integer/ParsingTest.java +++ b/test/jdk/java/lang/Integer/ParsingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2007, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 5017980 6576055 8041972 8055251 * @summary Test parsing methods + * @author Joseph D. Darcy */ import java.lang.IndexOutOfBoundsException; diff --git a/test/jdk/java/lang/Integer/Unsigned.java b/test/jdk/java/lang/Integer/Unsigned.java index 911f3f8fe8fc3..6c3aecc70c11f 100644 --- a/test/jdk/java/lang/Integer/Unsigned.java +++ b/test/jdk/java/lang/Integer/Unsigned.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 4504839 4215269 6322074 * @summary Basic tests for unsigned operations. + * @author Joseph D. Darcy */ public class Unsigned { public static void main(String... args) { diff --git a/test/jdk/java/lang/Long/Decode.java b/test/jdk/java/lang/Long/Decode.java index fc2762b1bc2b7..d47f976e6fc4b 100644 --- a/test/jdk/java/lang/Long/Decode.java +++ b/test/jdk/java/lang/Long/Decode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ * @test * @bug 4136371 5017980 6576055 * @summary Test Long.decode method + * @author madbot + * @author Joseph D. Darcy */ import java.math.BigInteger; diff --git a/test/jdk/java/lang/Long/ParsingTest.java b/test/jdk/java/lang/Long/ParsingTest.java index 23d007dfd2625..cbf83415d3612 100644 --- a/test/jdk/java/lang/Long/ParsingTest.java +++ b/test/jdk/java/lang/Long/ParsingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2007, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 5017980 6576055 8041972 8055251 * @summary Test parsing methods + * @author Joseph D. Darcy */ /** diff --git a/test/jdk/java/lang/Long/Unsigned.java b/test/jdk/java/lang/Long/Unsigned.java index aba66c72a92f9..f6eeed534b8cc 100644 --- a/test/jdk/java/lang/Long/Unsigned.java +++ b/test/jdk/java/lang/Long/Unsigned.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -25,6 +25,7 @@ * @test * @bug 4504839 4215269 6322074 8030814 * @summary Basic tests for unsigned operations + * @author Joseph D. Darcy */ import java.math.*; diff --git a/test/jdk/java/lang/Short/Decode.java b/test/jdk/java/lang/Short/Decode.java index d63e911b710a4..8f76751b58960 100644 --- a/test/jdk/java/lang/Short/Decode.java +++ b/test/jdk/java/lang/Short/Decode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ * @test * @bug 4136371 5017980 6576055 * @summary Test Short.decode method + * @author madbot + * @author Joseph D. Darcy */ /** diff --git a/test/jdk/java/lang/StackWalker/CallerFromMain.java b/test/jdk/java/lang/StackWalker/CallerFromMain.java index 81456b02c36e6..86e7cfb7043da 100644 --- a/test/jdk/java/lang/StackWalker/CallerFromMain.java +++ b/test/jdk/java/lang/StackWalker/CallerFromMain.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2023, 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 @@ -24,9 +24,8 @@ /* * @test * @bug 8140450 - * @summary Test if the getCallerClass method returns empty optional - * @requires test.thread.factory == null * @library /test/lib + * @summary Test if the getCallerClass method returns empty optional * @run main CallerFromMain exec */ diff --git a/test/jdk/java/lang/StackWalker/DumpStackTest.java b/test/jdk/java/lang/StackWalker/DumpStackTest.java index 1365e39ccfa26..c196b1c4ad337 100644 --- a/test/jdk/java/lang/StackWalker/DumpStackTest.java +++ b/test/jdk/java/lang/StackWalker/DumpStackTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 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 @@ * @summary Verify outputs of Thread.dumpStack() and Throwable.printStackTrace(). * This test should also been run against jdk9 successfully except of * VM option MemberNameInStackFrame. - * @requires test.thread.factory == null * @run main/othervm DumpStackTest */ diff --git a/test/jdk/java/lang/StackWalker/StackWalkTest.java b/test/jdk/java/lang/StackWalker/StackWalkTest.java index 8848f323cab88..80e934d477ce0 100644 --- a/test/jdk/java/lang/StackWalker/StackWalkTest.java +++ b/test/jdk/java/lang/StackWalker/StackWalkTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,6 @@ * @test * @bug 8140450 * @summary Stack Walk Test (use -Dseed=X to set PRNG seed) - * @requires test.thread.factory == null * @library /test/lib * @build jdk.test.lib.RandomFactory * @compile StackRecorderUtil.java diff --git a/test/jdk/java/lang/Thread/MainThreadTest.java b/test/jdk/java/lang/Thread/MainThreadTest.java index 7129170ad4eba..2482a8aa6d29e 100644 --- a/test/jdk/java/lang/Thread/MainThreadTest.java +++ b/test/jdk/java/lang/Thread/MainThreadTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 4533087 * @summary Test to see if the main thread is in its thread group - * @requires test.thread.factory == null */ public class MainThreadTest { diff --git a/test/jdk/java/lang/Thread/UncaughtExceptionsTest.java b/test/jdk/java/lang/Thread/UncaughtExceptionsTest.java index 1bb810d372fd3..915d1cb6b76fb 100644 --- a/test/jdk/java/lang/Thread/UncaughtExceptionsTest.java +++ b/test/jdk/java/lang/Thread/UncaughtExceptionsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,6 @@ * @bug 4833089 4992454 * @summary Check for proper handling of uncaught exceptions * @author Martin Buchholz - * @requires test.thread.factory == null * @library /test/lib * @build jdk.test.lib.process.* * @run junit UncaughtExceptionsTest diff --git a/test/jdk/java/lang/Throwable/SuppressedExceptions.java b/test/jdk/java/lang/Throwable/SuppressedExceptions.java index 157a4ffa99b7e..f6fe09df4ef67 100644 --- a/test/jdk/java/lang/Throwable/SuppressedExceptions.java +++ b/test/jdk/java/lang/Throwable/SuppressedExceptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2013, 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 @@ * @test * @bug 6911258 6962571 6963622 6991528 7005628 8012044 * @summary Basic tests of suppressed exceptions + * @author Joseph D. Darcy */ public class SuppressedExceptions { diff --git a/test/jdk/java/lang/annotation/Missing/MissingTest.java b/test/jdk/java/lang/annotation/Missing/MissingTest.java index 10e3b436d1264..d8a1c44e7eeab 100644 --- a/test/jdk/java/lang/annotation/Missing/MissingTest.java +++ b/test/jdk/java/lang/annotation/Missing/MissingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 6322301 5041778 * @summary Verify when missing annotation classes cause exceptions + * @author Joseph D. Darcy * @compile MissingTest.java A.java B.java C.java D.java Marker.java Missing.java MissingWrapper.java MissingDefault.java * @clean Missing * @run main MissingTest diff --git a/test/jdk/java/lang/annotation/TestIncompleteAnnotationExceptionNPE.java b/test/jdk/java/lang/annotation/TestIncompleteAnnotationExceptionNPE.java index 390f0fc96bd76..9e9e7a7a60a74 100644 --- a/test/jdk/java/lang/annotation/TestIncompleteAnnotationExceptionNPE.java +++ b/test/jdk/java/lang/annotation/TestIncompleteAnnotationExceptionNPE.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 7021922 * @summary Test null handling of IncompleteAnnotationException constructor + * @author Joseph D. Darcy */ import java.lang.annotation.*; diff --git a/test/jdk/java/lang/module/customfs/ModulesInCustomFileSystem.java b/test/jdk/java/lang/module/customfs/ModulesInCustomFileSystem.java index e023a3a5839b3..801f2e5fca6cf 100644 --- a/test/jdk/java/lang/module/customfs/ModulesInCustomFileSystem.java +++ b/test/jdk/java/lang/module/customfs/ModulesInCustomFileSystem.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, 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,7 +28,7 @@ * @library /test/lib * @build ModulesInCustomFileSystem m1/* m2/* * jdk.test.lib.util.JarUtils - * @run testng/othervm -Djava.io.tmpdir=. ModulesInCustomFileSystem + * @run testng/othervm ModulesInCustomFileSystem * @summary Test ModuleFinder to find modules in a custom file system */ diff --git a/test/jdk/java/lang/ref/OOMEInReferenceHandler.java b/test/jdk/java/lang/ref/OOMEInReferenceHandler.java index 9f0a4ea378ea4..2f80fa6178ab5 100644 --- a/test/jdk/java/lang/ref/OOMEInReferenceHandler.java +++ b/test/jdk/java/lang/ref/OOMEInReferenceHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 7038914 8016341 * @summary Verify that the reference handler does not die after an OOME allocating the InterruptedException object - * @requires test.thread.factory == null * @run main/othervm -XX:-UseGCOverheadLimit -Xmx24M -XX:-UseTLAB OOMEInReferenceHandler * @author peter.levart@gmail.com * @key intermittent diff --git a/test/jdk/java/lang/reflect/AnnotatedElement/TestAnnotatedElementDefaults.java b/test/jdk/java/lang/reflect/AnnotatedElement/TestAnnotatedElementDefaults.java index 34c4f8402419a..97e9a79e14b42 100644 --- a/test/jdk/java/lang/reflect/AnnotatedElement/TestAnnotatedElementDefaults.java +++ b/test/jdk/java/lang/reflect/AnnotatedElement/TestAnnotatedElementDefaults.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 8005294 * @summary Check behavior of default methods of AnnotatedElement + * @author Joseph D. Darcy */ import java.lang.annotation.*; diff --git a/test/jdk/java/lang/reflect/Constructor/GenericStringTest.java b/test/jdk/java/lang/reflect/Constructor/GenericStringTest.java index a8c6c671d8606..56a781fce1854 100644 --- a/test/jdk/java/lang/reflect/Constructor/GenericStringTest.java +++ b/test/jdk/java/lang/reflect/Constructor/GenericStringTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 5033583 6316717 6470106 8161500 8162539 6304578 * @summary Check toGenericString() and toString() methods + * @author Joseph D. Darcy */ import java.lang.reflect.*; diff --git a/test/jdk/java/lang/reflect/Constructor/TestParameterAnnotations.java b/test/jdk/java/lang/reflect/Constructor/TestParameterAnnotations.java index 7512d36cb4237..5773825a8e2ba 100644 --- a/test/jdk/java/lang/reflect/Constructor/TestParameterAnnotations.java +++ b/test/jdk/java/lang/reflect/Constructor/TestParameterAnnotations.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 6332964 * @summary Verify getParameterAnnotations doesn't throw spurious errors + * @author Joseph D. Darcy */ import java.lang.reflect.*; diff --git a/test/jdk/java/lang/reflect/DefaultAccessibility.java b/test/jdk/java/lang/reflect/DefaultAccessibility.java index 69f8946e6173e..6dce3e249c2b5 100644 --- a/test/jdk/java/lang/reflect/DefaultAccessibility.java +++ b/test/jdk/java/lang/reflect/DefaultAccessibility.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 6648344 * @summary Test that default accessibility is false + * @author Joseph D. Darcy */ import java.lang.reflect.*; diff --git a/test/jdk/java/lang/reflect/Field/GenericStringTest.java b/test/jdk/java/lang/reflect/Field/GenericStringTest.java index 5b5c321a3e11e..65fbbc433812c 100644 --- a/test/jdk/java/lang/reflect/Field/GenericStringTest.java +++ b/test/jdk/java/lang/reflect/Field/GenericStringTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 5033583 8161500 * @summary Check toGenericString() method + * @author Joseph D. Darcy */ import java.lang.reflect.*; diff --git a/test/jdk/java/lang/reflect/Generics/HashCodeTest.java b/test/jdk/java/lang/reflect/Generics/HashCodeTest.java index 00e1494d04a49..53fbad758d0b4 100644 --- a/test/jdk/java/lang/reflect/Generics/HashCodeTest.java +++ b/test/jdk/java/lang/reflect/Generics/HashCodeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 5097856 * @summary Computing hashCode of objects modeling generics shouldn't blow stack + * @author Joseph D. Darcy */ import java.util.*; diff --git a/test/jdk/java/lang/reflect/Generics/Probe.java b/test/jdk/java/lang/reflect/Generics/Probe.java index e14ed54f86318..cbe94aef7a40c 100644 --- a/test/jdk/java/lang/reflect/Generics/Probe.java +++ b/test/jdk/java/lang/reflect/Generics/Probe.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 5003916 6704655 6873951 6476261 8004928 * @summary Testing parsing of signatures attributes of nested classes + * @author Joseph D. Darcy */ import java.lang.reflect.*; diff --git a/test/jdk/java/lang/reflect/Generics/StringsAndBounds.java b/test/jdk/java/lang/reflect/Generics/StringsAndBounds.java index 5c44207bcc51b..6d7756b2163a0 100644 --- a/test/jdk/java/lang/reflect/Generics/StringsAndBounds.java +++ b/test/jdk/java/lang/reflect/Generics/StringsAndBounds.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 5015676 4987888 4997464 * @summary Testing upper bounds and availability of toString methods + * @author Joseph D. Darcy */ import java.lang.reflect.*; diff --git a/test/jdk/java/lang/reflect/Generics/TestParameterizedType.java b/test/jdk/java/lang/reflect/Generics/TestParameterizedType.java index 99fc3db0c97a7..6bb3aa47aef3b 100644 --- a/test/jdk/java/lang/reflect/Generics/TestParameterizedType.java +++ b/test/jdk/java/lang/reflect/Generics/TestParameterizedType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 5061485 * @summary Test sematics of ParameterizedType.equals + * @author Joseph D. Darcy */ import java.util.*; diff --git a/test/jdk/java/lang/reflect/Generics/exceptionCauseTest.java b/test/jdk/java/lang/reflect/Generics/exceptionCauseTest.java index 485e8d3c51ed4..dc8397aded6b1 100644 --- a/test/jdk/java/lang/reflect/Generics/exceptionCauseTest.java +++ b/test/jdk/java/lang/reflect/Generics/exceptionCauseTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 4981727 * @summary + * @author Joseph D. Darcy */ import java.io.PrintStream; diff --git a/test/jdk/java/lang/reflect/Generics/getAnnotationTest.java b/test/jdk/java/lang/reflect/Generics/getAnnotationTest.java index 766543863d069..0e1317e8d2de1 100644 --- a/test/jdk/java/lang/reflect/Generics/getAnnotationTest.java +++ b/test/jdk/java/lang/reflect/Generics/getAnnotationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 4979440 * @summary Test for signature parsing corner case + * @author Joseph D. Darcy */ import java.lang.reflect.*; diff --git a/test/jdk/java/lang/reflect/Method/GenericStringTest.java b/test/jdk/java/lang/reflect/Method/GenericStringTest.java index e7fe873d3cc19..c1c8e141f7924 100644 --- a/test/jdk/java/lang/reflect/Method/GenericStringTest.java +++ b/test/jdk/java/lang/reflect/Method/GenericStringTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2021, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 5033583 6316717 6470106 8004979 8161500 8162539 6304578 * @summary Check toGenericString() and toString() methods + * @author Joseph D. Darcy */ import java.lang.reflect.*; diff --git a/test/jdk/java/lang/reflect/Method/IsDefaultTest.java b/test/jdk/java/lang/reflect/Method/IsDefaultTest.java index 0c983a8b0bac3..c48ebaf9e963d 100644 --- a/test/jdk/java/lang/reflect/Method/IsDefaultTest.java +++ b/test/jdk/java/lang/reflect/Method/IsDefaultTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 8005042 * @summary Check behavior of Method.isDefault + * @author Joseph D. Darcy */ import java.lang.reflect.*; diff --git a/test/jdk/java/lang/reflect/Method/defaultMethodModeling/DefaultMethodModeling.java b/test/jdk/java/lang/reflect/Method/defaultMethodModeling/DefaultMethodModeling.java index b91f73ee84515..30eca409cea77 100644 --- a/test/jdk/java/lang/reflect/Method/defaultMethodModeling/DefaultMethodModeling.java +++ b/test/jdk/java/lang/reflect/Method/defaultMethodModeling/DefaultMethodModeling.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 8011590 * @summary Check modeling of default methods + * @author Joseph D. Darcy */ import java.util.Objects; diff --git a/test/jdk/java/lang/reflect/TypeVariable/TestAnnotatedElement.java b/test/jdk/java/lang/reflect/TypeVariable/TestAnnotatedElement.java index 9788eab3060c3..94f8d459cf0e2 100644 --- a/test/jdk/java/lang/reflect/TypeVariable/TestAnnotatedElement.java +++ b/test/jdk/java/lang/reflect/TypeVariable/TestAnnotatedElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 7086192 * @summary Verify functionality of AnnotatedElement methods on type variables + * @author Joseph D. Darcy */ import java.lang.reflect.*; diff --git a/test/jdk/java/math/BigDecimal/AddTests.java b/test/jdk/java/math/BigDecimal/AddTests.java index d6f57366d2a64..8045e28043575 100644 --- a/test/jdk/java/math/BigDecimal/AddTests.java +++ b/test/jdk/java/math/BigDecimal/AddTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 6362557 8200698 * @summary Some tests of add(BigDecimal, mc) + * @author Joseph D. Darcy */ import java.math.*; diff --git a/test/jdk/java/math/BigDecimal/CompareToTests.java b/test/jdk/java/math/BigDecimal/CompareToTests.java index b6ae31bca80c3..baefcc5b49958 100644 --- a/test/jdk/java/math/BigDecimal/CompareToTests.java +++ b/test/jdk/java/math/BigDecimal/CompareToTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 6473768 * @summary Tests of BigDecimal.compareTo + * @author Joseph D. Darcy */ import java.math.*; import static java.math.BigDecimal.*; diff --git a/test/jdk/java/math/BigDecimal/DivideTests.java b/test/jdk/java/math/BigDecimal/DivideTests.java index 140271dc0008f..fe0fea73ff6d3 100644 --- a/test/jdk/java/math/BigDecimal/DivideTests.java +++ b/test/jdk/java/math/BigDecimal/DivideTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 4851776 4907265 6177836 6876282 8066842 * @summary Some tests for the divide methods. + * @author Joseph D. Darcy */ import java.math.*; diff --git a/test/jdk/java/math/BigDecimal/IntegralDivisionTests.java b/test/jdk/java/math/BigDecimal/IntegralDivisionTests.java index 7df63b6329f57..9fab5bb28ae81 100644 --- a/test/jdk/java/math/BigDecimal/IntegralDivisionTests.java +++ b/test/jdk/java/math/BigDecimal/IntegralDivisionTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, 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 @@ -24,6 +24,7 @@ * @test * @bug 4904082 4917089 6337226 6378503 * @summary Tests that integral division and related methods return the proper result and scale. + * @author Joseph D. Darcy */ import java.math.*; public class IntegralDivisionTests { diff --git a/test/jdk/java/math/BigDecimal/NegateTests.java b/test/jdk/java/math/BigDecimal/NegateTests.java index fc4ce82e28658..5b570325e9037 100644 --- a/test/jdk/java/math/BigDecimal/NegateTests.java +++ b/test/jdk/java/math/BigDecimal/NegateTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 6325535 * @summary Test for the rounding behavior of negate(MathContext) + * @author Joseph D. Darcy */ import java.math.*; diff --git a/test/jdk/java/math/BigDecimal/PowTests.java b/test/jdk/java/math/BigDecimal/PowTests.java index a552e981c2ecd..49fc74c879120 100644 --- a/test/jdk/java/math/BigDecimal/PowTests.java +++ b/test/jdk/java/math/BigDecimal/PowTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 4916097 * @summary Some exponent over/undeflow tests for the pow method + * @author Joseph D. Darcy */ import java.math.*; diff --git a/test/jdk/java/math/BigDecimal/PrecisionTests.java b/test/jdk/java/math/BigDecimal/PrecisionTests.java index 88d9843c72491..43df43e16bc3f 100644 --- a/test/jdk/java/math/BigDecimal/PrecisionTests.java +++ b/test/jdk/java/math/BigDecimal/PrecisionTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 1234567 * @summary Test that precision() is computed properly. + * @author Joseph D. Darcy */ import java.math.*; diff --git a/test/jdk/java/math/BigDecimal/RoundingTests.java b/test/jdk/java/math/BigDecimal/RoundingTests.java index 6a12124fd62de..95d579e791af0 100644 --- a/test/jdk/java/math/BigDecimal/RoundingTests.java +++ b/test/jdk/java/math/BigDecimal/RoundingTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 6334849 * @summary Tests of dropping digits near the scale threshold + * @author Joseph D. Darcy */ import java.math.*; public class RoundingTests { diff --git a/test/jdk/java/math/BigDecimal/ScaleByPowerOfTenTests.java b/test/jdk/java/math/BigDecimal/ScaleByPowerOfTenTests.java index 93131b77be2f1..638fce9ed545c 100644 --- a/test/jdk/java/math/BigDecimal/ScaleByPowerOfTenTests.java +++ b/test/jdk/java/math/BigDecimal/ScaleByPowerOfTenTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 4899722 * @summary Basic tests of scaleByPowerOfTen + * @author Joseph D. Darcy */ import java.math.*; diff --git a/test/jdk/java/math/BigDecimal/SquareRootTests.java b/test/jdk/java/math/BigDecimal/SquareRootTests.java index 1a685c8483aaa..7d9fce4caa0d8 100644 --- a/test/jdk/java/math/BigDecimal/SquareRootTests.java +++ b/test/jdk/java/math/BigDecimal/SquareRootTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -348,7 +348,7 @@ private static int lowPrecisionPerfectSquares() { for (int scale = 0; scale <= 4; scale++) { BigDecimal scaledSquare = square.setScale(scale, RoundingMode.UNNECESSARY); - int expectedScale = Math.ceilDiv(scale, 2); + int expectedScale = scale/2; for (int precision = 0; precision <= 5; precision++) { for (RoundingMode rm : RoundingMode.values()) { MathContext mc = new MathContext(precision, rm); @@ -582,8 +582,7 @@ public static BigDecimal sqrt(BigDecimal bd, MathContext mc) { // The code below favors relative simplicity over checking // for special cases that could run faster. - int preferredScale = Math.ceilDiv(bd.scale(), 2); - + int preferredScale = bd.scale()/2; BigDecimal zeroWithFinalPreferredScale = BigDecimal.valueOf(0L, preferredScale); diff --git a/test/jdk/java/math/BigDecimal/StrippingZerosTest.java b/test/jdk/java/math/BigDecimal/StrippingZerosTest.java index c79c26c0ce55c..083b4eabbf106 100644 --- a/test/jdk/java/math/BigDecimal/StrippingZerosTest.java +++ b/test/jdk/java/math/BigDecimal/StrippingZerosTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2018, 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,6 +27,7 @@ * @summary A few tests of stripTrailingZeros * @run main StrippingZerosTest * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+EliminateAutoBox -XX:AutoBoxCacheMax=20000 StrippingZerosTest + * @author Joseph D. Darcy */ import java.math.*; diff --git a/test/jdk/java/math/BigDecimal/ToPlainStringTests.java b/test/jdk/java/math/BigDecimal/ToPlainStringTests.java index 28d5cdcd89dce..0a1f617c0e578 100644 --- a/test/jdk/java/math/BigDecimal/ToPlainStringTests.java +++ b/test/jdk/java/math/BigDecimal/ToPlainStringTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2023, 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,6 +27,7 @@ * @summary Basic tests of toPlainString method * @run main ToPlainStringTests * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+EliminateAutoBox -XX:AutoBoxCacheMax=20000 ToPlainStringTests + * @author Joseph D. Darcy */ import java.math.*; diff --git a/test/jdk/java/math/BigDecimal/ZeroScalingTests.java b/test/jdk/java/math/BigDecimal/ZeroScalingTests.java index 908487d68ef3d..05a59150b1396 100644 --- a/test/jdk/java/math/BigDecimal/ZeroScalingTests.java +++ b/test/jdk/java/math/BigDecimal/ZeroScalingTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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,6 +27,7 @@ * @summary Tests that the scale of zero is propagated properly and has the * proper effect and that setting the scale to zero does not mutate the * BigDecimal. + * @author Joseph D. Darcy */ import java.math.*; diff --git a/test/jdk/java/math/BigInteger/CompareToTests.java b/test/jdk/java/math/BigInteger/CompareToTests.java index 3d9ff40ce56cd..4e549fa2a53c6 100644 --- a/test/jdk/java/math/BigInteger/CompareToTests.java +++ b/test/jdk/java/math/BigInteger/CompareToTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 6473768 * @summary Tests of BigInteger.compareTo + * @author Joseph D. Darcy */ import java.math.*; import static java.math.BigInteger.*; diff --git a/test/jdk/java/math/BigInteger/ExtremeShiftingTests.java b/test/jdk/java/math/BigInteger/ExtremeShiftingTests.java index a173d1cf6dd79..853b88668a26f 100644 --- a/test/jdk/java/math/BigInteger/ExtremeShiftingTests.java +++ b/test/jdk/java/math/BigInteger/ExtremeShiftingTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2013, 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,6 +27,7 @@ * @summary Tests of shiftLeft and shiftRight on Integer.MIN_VALUE * @requires os.maxMemory >= 1g * @run main/othervm -Xmx512m ExtremeShiftingTests + * @author Joseph D. Darcy */ import java.math.BigInteger; import static java.math.BigInteger.*; diff --git a/test/jdk/java/math/BigInteger/OperatorNpeTests.java b/test/jdk/java/math/BigInteger/OperatorNpeTests.java index 593e15445d52a..2985ae00c8e59 100644 --- a/test/jdk/java/math/BigInteger/OperatorNpeTests.java +++ b/test/jdk/java/math/BigInteger/OperatorNpeTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 6365176 * @summary Get NullPointerExceptions when expected + * @author Joseph D. Darcy */ import java.math.*; diff --git a/test/jdk/java/math/BigInteger/StringConstructor.java b/test/jdk/java/math/BigInteger/StringConstructor.java index aa95fd4e346d5..c8fd9f83c6bcc 100644 --- a/test/jdk/java/math/BigInteger/StringConstructor.java +++ b/test/jdk/java/math/BigInteger/StringConstructor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2007, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 4489146 5017980 * @summary tests String constructors of BigInteger + * @author Joseph D. Darcy */ import java.math.*; diff --git a/test/jdk/java/math/BigInteger/TestValueExact.java b/test/jdk/java/math/BigInteger/TestValueExact.java index fcd934653be49..63ee15835279f 100644 --- a/test/jdk/java/math/BigInteger/TestValueExact.java +++ b/test/jdk/java/math/BigInteger/TestValueExact.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 6371401 * @summary Tests of fooValueExact methods + * @author Joseph D. Darcy */ import java.math.BigInteger; diff --git a/test/jdk/java/math/RoundingMode/RoundingModeTests.java b/test/jdk/java/math/RoundingMode/RoundingModeTests.java index 6edccb9277d98..87ecad945b6f4 100644 --- a/test/jdk/java/math/RoundingMode/RoundingModeTests.java +++ b/test/jdk/java/math/RoundingMode/RoundingModeTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 4851776 4891522 4905335 * @summary Basic tests for the RoundingMode class. + * @author Joseph D. Darcy */ import java.math.RoundingMode; diff --git a/test/jdk/java/net/httpclient/BufferSize1Test.java b/test/jdk/java/net/httpclient/BufferSize1Test.java deleted file mode 100644 index 842dc06a630ac..0000000000000 --- a/test/jdk/java/net/httpclient/BufferSize1Test.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * 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. - */ - -import jdk.httpclient.test.lib.common.HttpServerAdapters; -import jdk.internal.net.http.common.Utils; -import jdk.test.lib.net.SimpleSSLContext; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.MethodSource; - -import javax.net.ssl.SSLContext; -import java.io.IOException; -import java.net.URI; -import java.net.http.HttpClient; -import java.net.http.HttpClient.Version; -import java.net.http.HttpRequest; -import java.net.http.HttpResponse; -import java.nio.charset.StandardCharsets; -import java.util.Arrays; - -import static java.net.http.HttpClient.Builder.NO_PROXY; -import static java.net.http.HttpClient.Version.HTTP_1_1; -import static java.net.http.HttpClient.Version.HTTP_2; -import static java.net.http.HttpClient.Version.HTTP_3; -import static java.net.http.HttpOption.H3_DISCOVERY; -import static java.net.http.HttpOption.Http3DiscoveryMode.HTTP_3_URI_ONLY; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; - -/* - * @test id - * @bug 8367976 - * @summary Verifies that setting the `jdk.httpclient.bufsize` system property - * to its lowest possible value, 1, does not wedge the client - * @library /test/jdk/java/net/httpclient/lib - * /test/lib - * @run junit/othervm -Djdk.httpclient.bufsize=1 BufferSize1Test - */ - -class BufferSize1Test implements HttpServerAdapters { - - @BeforeAll - static void verifyBufferSize() { - assertEquals(1, Utils.BUFSIZE); - } - - static Object[][] testArgs() { - return new Object[][]{ - {HTTP_1_1, false}, - {HTTP_1_1, true}, - {HTTP_2, false}, - {HTTP_2, true}, - {HTTP_3, true} - }; - } - - @ParameterizedTest - @MethodSource("testArgs") - void test(Version version, boolean secure) throws Exception { - - // Create the server - var sslContext = secure || HTTP_3.equals(version) ? new SimpleSSLContext().get() : null; - try (var server = switch (version) { - case HTTP_1_1, HTTP_2 -> HttpTestServer.create(version, sslContext); - case HTTP_3 -> HttpTestServer.create(HTTP_3_URI_ONLY, sslContext); - }) { - - // Add the handler and start the server - var serverHandlerPath = "/" + BufferSize1Test.class.getSimpleName(); - server.addHandler(new HttpTestEchoHandler(), serverHandlerPath); - server.start(); - - // Create the client - try (var client = createClient(version, sslContext)) { - - // Create the request with body to ensure that `ByteBuffer`s - // will be used throughout the entire end-to-end interaction. - byte[] requestBodyBytes = "body".repeat(1000).getBytes(StandardCharsets.US_ASCII); - var request = createRequest(sslContext, server, serverHandlerPath, version, requestBodyBytes); - - // Execute and verify the request. - // Do it twice to cover code paths before and after a protocol upgrade. - requestAndVerify(client, request, requestBodyBytes); - requestAndVerify(client, request, requestBodyBytes); - - } - - } - - } - - private HttpClient createClient(Version version, SSLContext sslContext) { - var clientBuilder = newClientBuilderForH3() - .proxy(NO_PROXY) - .version(version); - if (sslContext != null) { - clientBuilder.sslContext(sslContext); - } - return clientBuilder.build(); - } - - private static HttpRequest createRequest( - SSLContext sslContext, - HttpTestServer server, - String serverHandlerPath, - Version version, - byte[] requestBodyBytes) { - var requestUri = URI.create(String.format( - "%s://%s%s/x", - sslContext == null ? "http" : "https", - server.serverAuthority(), - serverHandlerPath)); - var requestBuilder = HttpRequest - .newBuilder(requestUri) - .version(version) - .POST(HttpRequest.BodyPublishers.ofByteArray(requestBodyBytes)); - if (HTTP_3.equals(version)) { - requestBuilder.setOption(H3_DISCOVERY, HTTP_3_URI_ONLY); - } - return requestBuilder.build(); - } - - private static void requestAndVerify(HttpClient client, HttpRequest request, byte[] requestBodyBytes) - throws IOException, InterruptedException { - var response = client.send(request, HttpResponse.BodyHandlers.ofByteArray()); - if (response.statusCode() != 200) { - throw new AssertionError("Was expecting status code 200, found: " + response.statusCode()); - } - byte[] responseBodyBytes = response.body(); - int mismatchIndex = Arrays.mismatch(requestBodyBytes, responseBodyBytes); - assertTrue( - mismatchIndex < 0, - String.format( - "Response body (%s bytes) mismatches the request body (%s bytes) at index %s!", - responseBodyBytes.length, requestBodyBytes.length, mismatchIndex)); - } - -} diff --git a/test/jdk/java/net/httpclient/BufferSizePropertyClampTest.java b/test/jdk/java/net/httpclient/BufferSizePropertyClampTest.java deleted file mode 100644 index caef0a58a6dc7..0000000000000 --- a/test/jdk/java/net/httpclient/BufferSizePropertyClampTest.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * 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. - */ - -import jdk.internal.net.http.common.Utils; -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.logging.Handler; -import java.util.logging.LogRecord; -import java.util.logging.Logger; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -/* - * @test - * @bug 8367976 - * @summary Verifies that the `jdk.httpclient.bufsize` system property is - * clamped correctly - * - * @library /test/lib - * - * @comment `-Djdk.httpclient.HttpClient.log=errors` is needed to enable - * logging and verify that invalid input gets logged - * @run junit/othervm - * -Djdk.httpclient.HttpClient.log=errors - * -Djdk.httpclient.bufsize=-1 - * BufferSizePropertyClampTest - * @run junit/othervm - * -Djdk.httpclient.HttpClient.log=errors - * -Djdk.httpclient.bufsize=0 - * BufferSizePropertyClampTest - * @run junit/othervm - * -Djdk.httpclient.HttpClient.log=errors - * -Djdk.httpclient.bufsize=16385 - * BufferSizePropertyClampTest - */ - -class BufferSizePropertyClampTest { - - /** Anchor to avoid the {@code Logger} instance get GC'ed */ - private static final Logger CLIENT_LOGGER = - Logger.getLogger("jdk.httpclient.HttpClient"); - - private static final List CLIENT_LOGGER_MESSAGES = - Collections.synchronizedList(new ArrayList<>()); - - @BeforeAll - static void registerLoggerHandler() { - CLIENT_LOGGER.addHandler(new Handler() { - - @Override - public void publish(LogRecord record) { - var message = MessageFormat.format(record.getMessage(), record.getParameters()); - CLIENT_LOGGER_MESSAGES.add(message); - } - - @Override - public void flush() { - // Do nothing - } - - @Override - public void close() { - // Do nothing - } - - }); - } - - @Test - void test() { - assertEquals(16384, Utils.BUFSIZE); - assertEquals( - 1, CLIENT_LOGGER_MESSAGES.size(), - "Unexpected number of logger messages: " + CLIENT_LOGGER_MESSAGES); - var expectedMessage = "ERROR: Property value for jdk.httpclient.bufsize=" + - System.getProperty("jdk.httpclient.bufsize") + - " not in [1..16384]: using default=16384"; - assertEquals(expectedMessage, CLIENT_LOGGER_MESSAGES.getFirst().replaceAll(",", "")); - } - -} diff --git a/test/jdk/java/net/httpclient/ContentLengthHeaderTest.java b/test/jdk/java/net/httpclient/ContentLengthHeaderTest.java index d7c77d0690a71..f302de4ee487c 100644 --- a/test/jdk/java/net/httpclient/ContentLengthHeaderTest.java +++ b/test/jdk/java/net/httpclient/ContentLengthHeaderTest.java @@ -29,9 +29,8 @@ * @library /test/lib /test/jdk/java/net/httpclient/lib * @build jdk.test.lib.net.SimpleSSLContext * jdk.httpclient.test.lib.common.HttpServerAdapters - * @bug 8283544 8358942 + * @bug 8283544 * @run testng/othervm - * -Djdk.httpclient.allowRestrictedHeaders=content-length * -Djdk.internal.httpclient.debug=true * ContentLengthHeaderTest */ @@ -96,8 +95,8 @@ public void setup() throws IOException, URISyntaxException, InterruptedException testContentLengthServerH2.addHandler(new NoContentLengthHandler(), NO_BODY_PATH); testContentLengthServerH3.addHandler(new NoContentLengthHandler(), NO_BODY_PATH); testContentLengthServerH1.addHandler(new ContentLengthHandler(), BODY_PATH); - testContentLengthServerH2.addHandler(new ContentLengthHandler(), BODY_PATH); - testContentLengthServerH3.addHandler(new ContentLengthHandler(), BODY_PATH); + testContentLengthServerH2.addHandler(new OptionalContentLengthHandler(), BODY_PATH); + testContentLengthServerH3.addHandler(new OptionalContentLengthHandler(), BODY_PATH); testContentLengthURIH1 = URIBuilder.newBuilder() .scheme("http") .loopback() @@ -164,13 +163,6 @@ Object[][] bodies() { }; } - @DataProvider(name = "h1body") - Object[][] h1body() { - return new Object[][]{ - {HTTP_1_1, URI.create(testContentLengthURIH1 + BODY_PATH)} - }; - } - @DataProvider(name = "nobodies") Object[][] nobodies() { return new Object[][]{ @@ -194,35 +186,6 @@ public void getWithNoBody(Version version, URI uri) throws IOException, Interrup assertEquals(resp.version(), version); } - @Test(dataProvider = "nobodies") - // A GET request with empty request body should have no Content-length header - public void getWithEmptyBody(Version version, URI uri) throws IOException, InterruptedException { - testLog.println(version + " Checking GET with no request body"); - HttpRequest req = HttpRequest.newBuilder() - .version(version) - .method("GET", HttpRequest.BodyPublishers.noBody()) - .uri(uri) - .build(); - HttpResponse resp = hc.send(req, HttpResponse.BodyHandlers.ofString(UTF_8)); - assertEquals(resp.statusCode(), 200, resp.body()); - assertEquals(resp.version(), version); - } - - @Test(dataProvider = "bodies") - // A GET request with empty request body and explicitly added Content-length header - public void getWithZeroContentLength(Version version, URI uri) throws IOException, InterruptedException { - testLog.println(version + " Checking GET with no request body"); - HttpRequest req = HttpRequest.newBuilder() - .version(version) - .method("GET", HttpRequest.BodyPublishers.noBody()) - .header("Content-length", "0") - .uri(uri) - .build(); - HttpResponse resp = hc.send(req, HttpResponse.BodyHandlers.ofString(UTF_8)); - assertEquals(resp.statusCode(), 200, resp.body()); - assertEquals(resp.version(), version); - } - @Test(dataProvider = "bodies") // A GET request with a request body should have a Content-length header // in HTTP/1.1 @@ -252,20 +215,6 @@ public void deleteWithNoBody(Version version, URI uri) throws IOException, Inter assertEquals(resp.version(), version); } - @Test(dataProvider = "nobodies") - // A DELETE request with empty request body should have no Content-length header - public void deleteWithEmptyBody(Version version, URI uri) throws IOException, InterruptedException { - testLog.println(version + " Checking DELETE with no request body"); - HttpRequest req = HttpRequest.newBuilder() - .version(version) - .method("DELETE", HttpRequest.BodyPublishers.noBody()) - .uri(uri) - .build(); - HttpResponse resp = hc.send(req, HttpResponse.BodyHandlers.ofString(UTF_8)); - assertEquals(resp.statusCode(), 200, resp.body()); - assertEquals(resp.version(), version); - } - @Test(dataProvider = "bodies") // A DELETE request with a request body should have a Content-length header // in HTTP/1.1 @@ -295,20 +244,6 @@ public void headWithNoBody(Version version, URI uri) throws IOException, Interru assertEquals(resp.version(), version); } - @Test(dataProvider = "nobodies") - // A HEAD request with empty request body should have no Content-length header - public void headWithEmptyBody(Version version, URI uri) throws IOException, InterruptedException { - testLog.println(version + " Checking HEAD with no request body"); - HttpRequest req = HttpRequest.newBuilder() - .version(version) - .method("HEAD", HttpRequest.BodyPublishers.noBody()) - .uri(uri) - .build(); - HttpResponse resp = hc.send(req, HttpResponse.BodyHandlers.ofString(UTF_8)); - assertEquals(resp.statusCode(), 200, resp.body()); - assertEquals(resp.version(), version); - } - @Test(dataProvider = "bodies") // A HEAD request with a request body should have a Content-length header // in HTTP/1.1 @@ -326,66 +261,6 @@ public void headWithBody(Version version, URI uri) throws IOException, Interrupt assertEquals(resp.version(), version); } - @Test(dataProvider = "h1body") - // A POST request with empty request body should have a Content-length header - // in HTTP/1.1 - public void postWithEmptyBody(Version version, URI uri) throws IOException, InterruptedException { - testLog.println(version + " Checking POST with request body"); - HttpRequest req = HttpRequest.newBuilder() - .version(version) - .method("POST", HttpRequest.BodyPublishers.noBody()) - .uri(uri) - .build(); - HttpResponse resp = hc.send(req, HttpResponse.BodyHandlers.ofString(UTF_8)); - assertEquals(resp.statusCode(), 200, resp.body()); - assertEquals(resp.version(), version); - } - - @Test(dataProvider = "bodies") - // A POST request with a request body should have a Content-length header - // in HTTP/1.1 - public void postWithBody(Version version, URI uri) throws IOException, InterruptedException { - testLog.println(version + " Checking POST with request body"); - HttpRequest req = HttpRequest.newBuilder() - .version(version) - .POST(HttpRequest.BodyPublishers.ofString("POST Body")) - .uri(uri) - .build(); - HttpResponse resp = hc.send(req, HttpResponse.BodyHandlers.ofString(UTF_8)); - assertEquals(resp.statusCode(), 200, resp.body()); - assertEquals(resp.version(), version); - } - - @Test(dataProvider = "h1body") - // A PUT request with empty request body should have a Content-length header - // in HTTP/1.1 - public void putWithEmptyBody(Version version, URI uri) throws IOException, InterruptedException { - testLog.println(version + " Checking PUT with request body"); - HttpRequest req = HttpRequest.newBuilder() - .version(version) - .method("PUT", HttpRequest.BodyPublishers.noBody()) - .uri(uri) - .build(); - HttpResponse resp = hc.send(req, HttpResponse.BodyHandlers.ofString(UTF_8)); - assertEquals(resp.statusCode(), 200, resp.body()); - assertEquals(resp.version(), version); - } - - @Test(dataProvider = "bodies") - // A PUT request with a request body should have a Content-length header - // in HTTP/1.1 - public void putWithBody(Version version, URI uri) throws IOException, InterruptedException { - testLog.println(version + " Checking PUT with request body"); - HttpRequest req = HttpRequest.newBuilder() - .version(version) - .PUT(HttpRequest.BodyPublishers.ofString("PUT Body")) - .uri(uri) - .build(); - HttpResponse resp = hc.send(req, HttpResponse.BodyHandlers.ofString(UTF_8)); - assertEquals(resp.statusCode(), 200, resp.body()); - assertEquals(resp.version(), version); - } - public static void handleResponse(long expected, HttpTestExchange ex, String body, int rCode) throws IOException { try (InputStream is = ex.getRequestBody()) { byte[] reqBody = is.readAllBytes(); @@ -449,4 +324,27 @@ public void handle(HttpTestExchange exchange) throws IOException { } } } + + /** + * A handler used for cases where the presence of a Content-Length + * header is optional. If present, its value must match the number of + * bytes sent in the request body. + */ + static class OptionalContentLengthHandler implements HttpTestHandler { + + @Override + public void handle(HttpTestExchange exchange) throws IOException { + testLog.println("OptionalContentLengthHandler: Received Headers " + + exchange.getRequestHeaders().entrySet() + + " from " + exchange.getRequestMethod() + " request."); + Optional contentLength = exchange.getRequestHeaders().firstValue("Content-Length"); + + // Check Content-length header was set + if (contentLength.isPresent()) { + handleResponse(Long.parseLong(contentLength.get()), exchange, "Request completed", 200); + } else { + handleResponse(-1, exchange, "Request completed, no content length", 200); + } + } + } } diff --git a/test/jdk/java/net/httpclient/HttpRequestBodyPublishers/OfByteArrayTest.java b/test/jdk/java/net/httpclient/HttpRequestBodyPublishers/OfByteArrayTest.java index 19f7369125dee..9973272b43513 100644 --- a/test/jdk/java/net/httpclient/HttpRequestBodyPublishers/OfByteArrayTest.java +++ b/test/jdk/java/net/httpclient/HttpRequestBodyPublishers/OfByteArrayTest.java @@ -43,6 +43,8 @@ * @run junit OfByteArrayTest * * @comment Using `main/othervm` to initiate tests that depend on a custom-configured JVM + * @run main/othervm -Djdk.httpclient.bufsize=-1 OfByteArrayTest testInvalidBufferSize + * @run main/othervm -Djdk.httpclient.bufsize=0 OfByteArrayTest testInvalidBufferSize * @run main/othervm -Djdk.httpclient.bufsize=3 OfByteArrayTest testChunking "" 0 0 "" * @run main/othervm -Djdk.httpclient.bufsize=3 OfByteArrayTest testChunking a 0 0 "" * @run main/othervm -Djdk.httpclient.bufsize=3 OfByteArrayTest testChunking a 1 0 "" @@ -86,6 +88,7 @@ void testInvalidOffsetOrLength(String contentText, int offset, int length) { */ public static void main(String[] args) throws InterruptedException { switch (args[0]) { + case "testInvalidBufferSize" -> testInvalidBufferSize(); case "testChunking" -> testChunking( parseStringArg(args[1]), Integer.parseInt(args[2]), @@ -99,6 +102,10 @@ private static String parseStringArg(String arg) { return arg == null || arg.trim().equals("\"\"") ? "" : arg; } + private static void testInvalidBufferSize() { + assertThrows(IllegalArgumentException.class, () -> HttpRequest.BodyPublishers.ofByteArray(new byte[1])); + } + private static void testChunking( String contentText, int offset, int length, String expectedBuffersText) throws InterruptedException { diff --git a/test/jdk/java/security/cert/CertPathBuilder/NoExtensions.java b/test/jdk/java/security/cert/CertPathBuilder/NoExtensions.java index e38d18dc9439f..7109d310d51a6 100644 --- a/test/jdk/java/security/cert/CertPathBuilder/NoExtensions.java +++ b/test/jdk/java/security/cert/CertPathBuilder/NoExtensions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,10 +25,8 @@ * @test * @bug 4519462 * @summary Verify Sun CertPathBuilder implementation handles certificates with no extensions - * @enablePreview */ -import java.security.PEMDecoder; import java.security.cert.X509Certificate; import java.security.cert.TrustAnchor; import java.security.cert.CollectionCertStoreParameters; @@ -37,15 +35,16 @@ import java.security.cert.CertPathBuilder; import java.security.cert.PKIXBuilderParameters; import java.security.cert.CertPathBuilderResult; +import java.security.cert.CertificateFactory; +import java.security.cert.CRL; import java.security.cert.CertPath; import java.util.HashSet; import java.util.ArrayList; +import java.io.ByteArrayInputStream; // Test based on user code submitted with bug by daniel.boggs@compass.net public class NoExtensions { - private static final PEMDecoder pemDecoder = PEMDecoder.of(); - public static void main(String[] args) { try { NoExtensions certs = new NoExtensions(); @@ -93,7 +92,7 @@ private void doBuild(X509Certificate userCert) throws Exception { // System.out.println(certPath.toString()); } - private static X509Certificate getTrustedCertificate() { + private static X509Certificate getTrustedCertificate() throws Exception { String sCert = "-----BEGIN CERTIFICATE-----\n" + "MIIBezCCASWgAwIBAgIQyWD8dLUoqpJFyDxrfRlrsTANBgkqhkiG9w0BAQQFADAW\n" @@ -105,10 +104,12 @@ private static X509Certificate getTrustedCertificate() { + "AKoAZIoRz7jUqlw19DANBgkqhkiG9w0BAQQFAANBACJxAfP57yqaT9N+nRgAOugM\n" + "JG0aN3/peCIvL3p29epRL2xoWFvxpUUlsH2I39OZ6b8+twWCebhkv1I62segXAk=\n" + "-----END CERTIFICATE-----"; - return pemDecoder.decode(sCert, X509Certificate.class); + CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); + ByteArrayInputStream bytes = new ByteArrayInputStream(sCert.getBytes()); + return (X509Certificate)certFactory.generateCertificate(bytes); } - private static X509Certificate getUserCertificate1() { + private static X509Certificate getUserCertificate1() throws Exception { // this certificate includes an extension String sCert = "-----BEGIN CERTIFICATE-----\n" @@ -122,10 +123,12 @@ private static X509Certificate getUserCertificate1() { + "CxeUaYlXmvbxVNkxM65Pplsj3h4ntfZaynmlhahH3YsnnA8wk6xPt04LjSId12RB\n" + "PeuO\n" + "-----END CERTIFICATE-----"; - return pemDecoder.decode(sCert, X509Certificate.class); + CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); + ByteArrayInputStream bytes = new ByteArrayInputStream(sCert.getBytes()); + return (X509Certificate)certFactory.generateCertificate(bytes); } - private static X509Certificate getUserCertificate2() { + private static X509Certificate getUserCertificate2() throws Exception { // this certificate does not include any extensions String sCert = "-----BEGIN CERTIFICATE-----\n" @@ -137,6 +140,8 @@ private static X509Certificate getUserCertificate2() { + "BAUAA0EAQmj9SFHEx66JyAps3ew4pcSS3QvfVZ/6qsNUYCG75rFGcTUPHcXKql9y\n" + "qBT83iNLJ//krjw5Ju0WRPg/buHSww==\n" + "-----END CERTIFICATE-----"; - return pemDecoder.decode(sCert, X509Certificate.class); + CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); + ByteArrayInputStream bytes = new ByteArrayInputStream(sCert.getBytes()); + return (X509Certificate)certFactory.generateCertificate(bytes); } } diff --git a/test/jdk/java/security/cert/CertPathBuilder/selfIssued/StatusLoopDependency.java b/test/jdk/java/security/cert/CertPathBuilder/selfIssued/StatusLoopDependency.java index 2a1514fae8abf..6524239416203 100644 --- a/test/jdk/java/security/cert/CertPathBuilder/selfIssued/StatusLoopDependency.java +++ b/test/jdk/java/security/cert/CertPathBuilder/selfIssued/StatusLoopDependency.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2014, 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 @@ -33,31 +33,18 @@ * @summary PIT b61: PKI test suite fails because self signed certificates * are being rejected * @modules java.base/sun.security.util - * @enablePreview * @run main/othervm StatusLoopDependency subca * @run main/othervm StatusLoopDependency subci * @run main/othervm StatusLoopDependency alice + * @author Xuelei Fan */ -import java.security.DEREncodable; -import java.security.PEMDecoder; +import java.io.*; +import java.net.SocketException; +import java.util.*; import java.security.Security; -import java.security.cert.CertPathBuilder; -import java.security.cert.CertStore; -import java.security.cert.Certificate; -import java.security.cert.CollectionCertStoreParameters; -import java.security.cert.PKIXBuilderParameters; -import java.security.cert.PKIXCertPathBuilderResult; -import java.security.cert.TrustAnchor; -import java.security.cert.X509CRL; -import java.security.cert.X509CertSelector; -import java.security.cert.X509Certificate; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.HashSet; -import java.util.Set; - +import java.security.cert.*; +import java.security.cert.CertPathValidatorException.BasicReason; import sun.security.util.DerInputStream; /** @@ -196,46 +183,61 @@ public final class StatusLoopDependency { "N9AvUXxGxU4DruoJuFPcrCI=\n" + "-----END X509 CRL-----"; - private static final PEMDecoder pemDecoder = PEMDecoder.of(); + private static Set generateTrustAnchors() + throws CertificateException { + // generate certificate from cert string + CertificateFactory cf = CertificateFactory.getInstance("X.509"); - private static Set generateTrustAnchors() { - X509Certificate selfSignedCert = pemDecoder.decode(selfSignedCertStr, X509Certificate.class); + ByteArrayInputStream is = + new ByteArrayInputStream(selfSignedCertStr.getBytes()); + Certificate selfSignedCert = cf.generateCertificate(is); // generate a trust anchor TrustAnchor anchor = - new TrustAnchor(selfSignedCert, null); + new TrustAnchor((X509Certificate)selfSignedCert, null); return Collections.singleton(anchor); } private static CertStore generateCertificateStore() throws Exception { + Collection entries = new HashSet(); + + // generate certificate from certificate string + CertificateFactory cf = CertificateFactory.getInstance("X.509"); - Collection entries = new HashSet<>(); + ByteArrayInputStream is; - DEREncodable cert = pemDecoder.decode(targetCertStr, X509Certificate.class); + is = new ByteArrayInputStream(targetCertStr.getBytes()); + Certificate cert = cf.generateCertificate(is); entries.add(cert); - cert = pemDecoder.decode(subCaCertStr, X509Certificate.class); + is = new ByteArrayInputStream(subCaCertStr.getBytes()); + cert = cf.generateCertificate(is); entries.add(cert); - cert = pemDecoder.decode(selfSignedCertStr, X509Certificate.class); + is = new ByteArrayInputStream(selfSignedCertStr.getBytes()); + cert = cf.generateCertificate(is); entries.add(cert); - cert = pemDecoder.decode(topCrlIssuerCertStr, X509Certificate.class); + is = new ByteArrayInputStream(topCrlIssuerCertStr.getBytes()); + cert = cf.generateCertificate(is); entries.add(cert); - cert = pemDecoder.decode(subCrlIssuerCertStr, X509Certificate.class); + is = new ByteArrayInputStream(subCrlIssuerCertStr.getBytes()); + cert = cf.generateCertificate(is); entries.add(cert); // generate CRL from CRL string - DEREncodable mixes = pemDecoder.decode(topCrlStr, X509CRL.class); - entries.add(mixes); + is = new ByteArrayInputStream(topCrlStr.getBytes()); + Collection mixes = cf.generateCRLs(is); + entries.addAll(mixes); - mixes = pemDecoder.decode(subCrlStr, X509CRL.class); - entries.add(mixes); + is = new ByteArrayInputStream(subCrlStr.getBytes()); + mixes = cf.generateCRLs(is); + entries.addAll(mixes); return CertStore.getInstance("Collection", - new CollectionCertStoreParameters(entries)); + new CollectionCertStoreParameters(entries)); } private static X509CertSelector generateSelector(String name) @@ -243,16 +245,17 @@ private static X509CertSelector generateSelector(String name) X509CertSelector selector = new X509CertSelector(); // generate certificate from certificate string - String cert; + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + ByteArrayInputStream is = null; if (name.equals("subca")) { - cert = subCaCertStr; + is = new ByteArrayInputStream(subCaCertStr.getBytes()); } else if (name.equals("subci")) { - cert = subCrlIssuerCertStr; + is = new ByteArrayInputStream(subCrlIssuerCertStr.getBytes()); } else { - cert = targetCertStr; + is = new ByteArrayInputStream(targetCertStr.getBytes()); } - X509Certificate target = pemDecoder.decode(cert, X509Certificate.class); + X509Certificate target = (X509Certificate)cf.generateCertificate(is); byte[] extVal = target.getExtensionValue("2.5.29.14"); if (extVal != null) { DerInputStream in = new DerInputStream(extVal); @@ -266,18 +269,21 @@ private static X509CertSelector generateSelector(String name) return selector; } - private static boolean match(String name, Certificate cert) { + private static boolean match(String name, Certificate cert) + throws Exception { + X509CertSelector selector = new X509CertSelector(); // generate certificate from certificate string - String newCert; + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + ByteArrayInputStream is = null; if (name.equals("subca")) { - newCert = subCaCertStr; + is = new ByteArrayInputStream(subCaCertStr.getBytes()); } else if (name.equals("subci")) { - newCert = subCrlIssuerCertStr; + is = new ByteArrayInputStream(subCrlIssuerCertStr.getBytes()); } else { - newCert = targetCertStr; + is = new ByteArrayInputStream(targetCertStr.getBytes()); } - X509Certificate target = pemDecoder.decode(newCert, X509Certificate.class); + X509Certificate target = (X509Certificate)cf.generateCertificate(is); return target.equals(cert); } diff --git a/test/jdk/java/security/cert/CertPathValidator/indirectCRL/CircularCRLTwoLevel.java b/test/jdk/java/security/cert/CertPathValidator/indirectCRL/CircularCRLTwoLevel.java index c83f1bc1f5d3a..d67db44e396df 100644 --- a/test/jdk/java/security/cert/CertPathValidator/indirectCRL/CircularCRLTwoLevel.java +++ b/test/jdk/java/security/cert/CertPathValidator/indirectCRL/CircularCRLTwoLevel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2014, 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 @@ -32,34 +32,16 @@ * * @bug 6720721 * @summary CRL check with circular depency support needed - * @enablePreview * @run main/othervm CircularCRLTwoLevel * @author Xuelei Fan */ -import java.security.DEREncodable; -import java.security.PEMDecoder; +import java.io.*; +import java.net.SocketException; +import java.util.*; import java.security.Security; -import java.security.cert.CertPath; -import java.security.cert.CertPathValidator; -import java.security.cert.CertPathValidatorException; +import java.security.cert.*; import java.security.cert.CertPathValidatorException.BasicReason; -import java.security.cert.CertStore; -import java.security.cert.Certificate; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.CollectionCertStoreParameters; -import java.security.cert.PKIXParameters; -import java.security.cert.TrustAnchor; -import java.security.cert.X509CRL; -import java.security.cert.X509Certificate; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.HashSet; -import java.util.List; -import java.util.Set; public class CircularCRLTwoLevel { @@ -167,19 +149,25 @@ public class CircularCRLTwoLevel { "ARGr6Qu68MYGtLMC6ZqP3u0=\n" + "-----END X509 CRL-----"; - private static final PEMDecoder pemDecoder = PEMDecoder.of(); - private static CertPath generateCertificatePath() throws CertificateException { // generate certificate from cert strings CertificateFactory cf = CertificateFactory.getInstance("X.509"); - Certificate targetCert = pemDecoder.decode(targetCertStr, X509Certificate.class); - Certificate subCaCert = pemDecoder.decode(subCaCertStr, X509Certificate.class); - Certificate selfSignedCert = pemDecoder.decode(selfSignedCertStr, X509Certificate.class); + ByteArrayInputStream is; + + is = new ByteArrayInputStream(targetCertStr.getBytes()); + Certificate targetCert = cf.generateCertificate(is); + + is = new ByteArrayInputStream(subCaCertStr.getBytes()); + Certificate subCaCert = cf.generateCertificate(is); + + is = new ByteArrayInputStream(selfSignedCertStr.getBytes()); + Certificate selfSignedCert = cf.generateCertificate(is); // generate certification path - List list = Arrays.asList(targetCert, subCaCert, selfSignedCert); + List list = Arrays.asList(new Certificate[] { + targetCert, subCaCert, selfSignedCert}); return cf.generateCertPath(list); } @@ -187,33 +175,42 @@ private static CertPath generateCertificatePath() private static Set generateTrustAnchors() throws CertificateException { // generate certificate from cert string + CertificateFactory cf = CertificateFactory.getInstance("X.509"); - final X509Certificate selfSignedCert = pemDecoder.decode(selfSignedCertStr, X509Certificate.class); + ByteArrayInputStream is = + new ByteArrayInputStream(selfSignedCertStr.getBytes()); + Certificate selfSignedCert = cf.generateCertificate(is); // generate a trust anchor TrustAnchor anchor = - new TrustAnchor(selfSignedCert, null); + new TrustAnchor((X509Certificate)selfSignedCert, null); return Collections.singleton(anchor); } private static CertStore generateCertificateStore() throws Exception { - Collection entries = new HashSet<>(); + Collection entries = new HashSet(); // generate CRL from CRL string + CertificateFactory cf = CertificateFactory.getInstance("X.509"); - DEREncodable mixes = pemDecoder.decode(topCrlStr, X509CRL.class); - entries.add(mixes); + ByteArrayInputStream is = + new ByteArrayInputStream(topCrlStr.getBytes()); + Collection mixes = cf.generateCRLs(is); + entries.addAll(mixes); - mixes = pemDecoder.decode(subCrlStr, X509CRL.class); - entries.add(mixes); + is = new ByteArrayInputStream(subCrlStr.getBytes()); + mixes = cf.generateCRLs(is); + entries.addAll(mixes); // intermediate certs - mixes = pemDecoder.decode(topCrlIssuerCertStr, X509Certificate.class); - entries.add(mixes); + is = new ByteArrayInputStream(topCrlIssuerCertStr.getBytes()); + mixes = cf.generateCertificates(is); + entries.addAll(mixes); - mixes = pemDecoder.decode(subCrlIssuerCertStr, X509Certificate.class); - entries.add(mixes); + is = new ByteArrayInputStream(subCrlIssuerCertStr.getBytes()); + mixes = cf.generateCertificates(is); + entries.addAll(mixes); return CertStore.getInstance("Collection", new CollectionCertStoreParameters(entries)); diff --git a/test/jdk/java/security/cert/CertPathValidator/indirectCRL/CircularCRLTwoLevelRevoked.java b/test/jdk/java/security/cert/CertPathValidator/indirectCRL/CircularCRLTwoLevelRevoked.java index 7ac63072737e9..e67934b8a19bb 100644 --- a/test/jdk/java/security/cert/CertPathValidator/indirectCRL/CircularCRLTwoLevelRevoked.java +++ b/test/jdk/java/security/cert/CertPathValidator/indirectCRL/CircularCRLTwoLevelRevoked.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2014, 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 @@ -32,34 +32,16 @@ * * @bug 6720721 * @summary CRL check with circular depency support needed - * @enablePreview * @run main/othervm CircularCRLTwoLevelRevoked * @author Xuelei Fan */ -import java.security.DEREncodable; -import java.security.PEMDecoder; +import java.io.*; +import java.net.SocketException; +import java.util.*; import java.security.Security; -import java.security.cert.CertPath; -import java.security.cert.CertPathValidator; -import java.security.cert.CertPathValidatorException; +import java.security.cert.*; import java.security.cert.CertPathValidatorException.BasicReason; -import java.security.cert.CertStore; -import java.security.cert.Certificate; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.CollectionCertStoreParameters; -import java.security.cert.PKIXParameters; -import java.security.cert.TrustAnchor; -import java.security.cert.X509CRL; -import java.security.cert.X509Certificate; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.HashSet; -import java.util.List; -import java.util.Set; public class CircularCRLTwoLevelRevoked { @@ -168,19 +150,25 @@ public class CircularCRLTwoLevelRevoked { "ARGr6Qu68MYGtLMC6ZqP3u0=\n" + "-----END X509 CRL-----"; - private static final PEMDecoder pemDecoder = PEMDecoder.of(); - private static CertPath generateCertificatePath() throws CertificateException { // generate certificate from cert strings CertificateFactory cf = CertificateFactory.getInstance("X.509"); - Certificate targetCert = pemDecoder.decode(targetCertStr, X509Certificate.class); - Certificate subCaCert = pemDecoder.decode(subCaCertStr, X509Certificate.class); - Certificate selfSignedCert = pemDecoder.decode(selfSignedCertStr, X509Certificate.class); + ByteArrayInputStream is; + + is = new ByteArrayInputStream(targetCertStr.getBytes()); + Certificate targetCert = cf.generateCertificate(is); + + is = new ByteArrayInputStream(subCaCertStr.getBytes()); + Certificate subCaCert = cf.generateCertificate(is); + + is = new ByteArrayInputStream(selfSignedCertStr.getBytes()); + Certificate selfSignedCert = cf.generateCertificate(is); // generate certification path - List list = Arrays.asList(targetCert, subCaCert, selfSignedCert); + List list = Arrays.asList(new Certificate[] { + targetCert, subCaCert, selfSignedCert}); return cf.generateCertPath(list); } @@ -188,36 +176,45 @@ private static CertPath generateCertificatePath() private static Set generateTrustAnchors() throws CertificateException { // generate certificate from cert string - final X509Certificate selfSignedCert = pemDecoder.decode(selfSignedCertStr, X509Certificate.class); + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + + ByteArrayInputStream is = + new ByteArrayInputStream(selfSignedCertStr.getBytes()); + Certificate selfSignedCert = cf.generateCertificate(is); // generate a trust anchor TrustAnchor anchor = - new TrustAnchor(selfSignedCert, null); + new TrustAnchor((X509Certificate)selfSignedCert, null); return Collections.singleton(anchor); } private static CertStore generateCertificateStore() throws Exception { - Collection entries = new HashSet<>(); + Collection entries = new HashSet(); // generate CRL from CRL string CertificateFactory cf = CertificateFactory.getInstance("X.509"); - DEREncodable mixes = pemDecoder.decode(topCrlStr, X509CRL.class); - entries.add(mixes); + ByteArrayInputStream is = + new ByteArrayInputStream(topCrlStr.getBytes()); + Collection mixes = cf.generateCRLs(is); + entries.addAll(mixes); - mixes = pemDecoder.decode(subCrlStr, X509CRL.class); - entries.add(mixes); + is = new ByteArrayInputStream(subCrlStr.getBytes()); + mixes = cf.generateCRLs(is); + entries.addAll(mixes); // intermediate certs - mixes = pemDecoder.decode(topCrlIssuerCertStr, X509Certificate.class); - entries.add(mixes); + is = new ByteArrayInputStream(topCrlIssuerCertStr.getBytes()); + mixes = cf.generateCertificates(is); + entries.addAll(mixes); - mixes = pemDecoder.decode(subCrlIssuerCertStr, X509Certificate.class); - entries.add(mixes); + is = new ByteArrayInputStream(subCrlIssuerCertStr.getBytes()); + mixes = cf.generateCertificates(is); + entries.addAll(mixes); return CertStore.getInstance("Collection", - new CollectionCertStoreParameters(entries)); + new CollectionCertStoreParameters(entries)); } public static void main(String args[]) throws Exception { diff --git a/test/jdk/java/time/tck/java/time/TCKDuration.java b/test/jdk/java/time/tck/java/time/TCKDuration.java index 2057e8e8939af..ee3950dec06df 100644 --- a/test/jdk/java/time/tck/java/time/TCKDuration.java +++ b/test/jdk/java/time/tck/java/time/TCKDuration.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2021, 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 @@ -71,8 +71,6 @@ import static java.time.temporal.ChronoUnit.WEEKS; import static java.time.temporal.ChronoUnit.YEARS; import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertNotEquals; -import static org.testng.Assert.assertThrows; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; @@ -117,44 +115,6 @@ public void test_zero() { assertEquals(Duration.ZERO.getNano(), 0); } - @Test - public void test_min() { - assertEquals(Duration.MIN.getSeconds(), Long.MIN_VALUE); - assertEquals(Duration.MIN.getNano(), 0); - // no duration minimally less than MIN - assertThrows(ArithmeticException.class, () -> Duration.MIN.minusNanos(1)); - } - - @Test - public void test_max() { - assertEquals(Duration.MAX.getSeconds(), Long.MAX_VALUE); - assertEquals(Duration.MAX.getNano(), 999_999_999); - // no duration minimally greater than MAX - assertThrows(ArithmeticException.class, () -> Duration.MAX.plusNanos(1)); - } - - @Test - public void test_constant_properties() { - assertTrue(Duration.MIN.compareTo(Duration.MIN) == 0); - assertEquals(Duration.MIN, Duration.MIN); - assertTrue(Duration.ZERO.compareTo(Duration.ZERO) == 0); - assertEquals(Duration.ZERO, Duration.ZERO); - assertTrue(Duration.MAX.compareTo(Duration.MAX) == 0); - assertEquals(Duration.MAX, Duration.MAX); - - assertTrue(Duration.MIN.compareTo(Duration.ZERO) < 0); - assertTrue(Duration.ZERO.compareTo(Duration.MIN) > 0); - assertNotEquals(Duration.ZERO, Duration.MIN); - - assertTrue(Duration.ZERO.compareTo(Duration.MAX) < 0); - assertTrue(Duration.MAX.compareTo(Duration.ZERO) > 0); - assertNotEquals(Duration.ZERO, Duration.MAX); - - assertTrue(Duration.MIN.compareTo(Duration.MAX) < 0); - assertTrue(Duration.MAX.compareTo(Duration.MIN) > 0); - assertNotEquals(Duration.MIN, Duration.MAX); - } - //----------------------------------------------------------------------- // ofSeconds(long) //----------------------------------------------------------------------- diff --git a/test/jdk/java/util/Locale/LocaleEnhanceTest.java b/test/jdk/java/util/Locale/LocaleEnhanceTest.java index 8bcbe20d19791..7ab8db4c9e255 100644 --- a/test/jdk/java/util/Locale/LocaleEnhanceTest.java +++ b/test/jdk/java/util/Locale/LocaleEnhanceTest.java @@ -31,8 +31,9 @@ import java.io.ObjectOutputStream; import java.net.URISyntaxException; import java.net.URL; -import java.nio.charset.StandardCharsets; import java.text.DecimalFormatSymbols; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Calendar; import java.util.IllformedLocaleException; import java.util.List; @@ -46,24 +47,26 @@ import org.junit.jupiter.params.provider.NullSource; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; -/* +/** * @test * @bug 6875847 6992272 7002320 7015500 7023613 7032820 7033504 7004603 * 7044019 8008577 8176853 8255086 8263202 8287868 8174269 8369452 - * 8369590 * @summary test API changes to Locale * @modules jdk.localedata + * @compile LocaleEnhanceTest.java * @run junit/othervm -esa LocaleEnhanceTest */ public class LocaleEnhanceTest { + public LocaleEnhanceTest() { + } + + /// + /// Generic sanity tests + /// + /** A canonical language code. */ private static final String l = "en"; @@ -76,10 +79,6 @@ public class LocaleEnhanceTest { /** A canonical variant code. */ private static final String v = "NewYork"; - /// - /// Generic sanity tests - /// - /** * Ensure that Builder builds locales that have the expected * tag and java6 ID. Note the odd cases for the ID. @@ -125,12 +124,12 @@ public void testCreateLocaleCanonicalValid() { .setRegion(idc) .setVariant(idv) .build(); - assertEquals(idl, l.getLanguage(), msg + "language"); - assertEquals(ids, l.getScript(), msg + "script"); - assertEquals(idc, l.getCountry(), msg + "country"); - assertEquals(idv, l.getVariant(), msg + "variant"); - assertEquals(tag, l.toLanguageTag(), msg + "tag"); - assertEquals(id, l.toString(), msg + "id"); + assertEquals(msg + "language", idl, l.getLanguage()); + assertEquals(msg + "script", ids, l.getScript()); + assertEquals(msg + "country", idc, l.getCountry()); + assertEquals(msg + "variant", idv, l.getVariant()); + assertEquals(msg + "tag", tag, l.toLanguageTag()); + assertEquals(msg + "id", id, l.toString()); } catch (IllegalArgumentException e) { fail(msg + e.getMessage()); @@ -182,13 +181,13 @@ public void testCreateLocaleMultipleVariants() { .setVariant(idv) .build(); - assertEquals(idl, l.getLanguage(), msg + " language"); - assertEquals(ids, l.getScript(), msg + " script"); - assertEquals(idc, l.getCountry(), msg + " country"); - assertEquals(idv, l.getVariant(), msg + " variant"); + assertEquals(msg + " language", idl, l.getLanguage()); + assertEquals(msg + " script", ids, l.getScript()); + assertEquals(msg + " country", idc, l.getCountry()); + assertEquals(msg + " variant", idv, l.getVariant()); - assertEquals(tag, l.toLanguageTag(), msg + "tag"); - assertEquals(id, l.toString(), msg + "id"); + assertEquals(msg + "tag", tag, l.toLanguageTag()); + assertEquals(msg + "id", id, l.toString()); } catch (IllegalArgumentException e) { fail(msg + e.getMessage()); @@ -236,7 +235,7 @@ public void testCreateLocaleCanonicalInvalidSeparator() { for (int i = 0; i < invalids.length; ++i) { String id = invalids[i]; Locale l = Locale.forLanguageTag(id); - assertEquals("und", l.toLanguageTag(), id); + assertEquals(id, "und", l.toLanguageTag()); } } @@ -256,14 +255,14 @@ public void testCurrentLocales() { // except no_NO_NY Locale tagResult = Locale.forLanguageTag(tag); if (!target.getVariant().equals("NY")) { - assertEquals(target, tagResult, "tagResult"); + assertEquals("tagResult", target, tagResult); } // the builder also recreates the original locale, // except ja_JP_JP, th_TH_TH and no_NO_NY Locale builderResult = builder.setLocale(target).build(); if (target.getVariant().length() != 2) { - assertEquals(target, builderResult, "builderResult"); + assertEquals("builderResult", target, builderResult); } } } @@ -276,11 +275,11 @@ public void testIcuLocales() throws Exception { BufferedReader br = new BufferedReader( new InputStreamReader( LocaleEnhanceTest.class.getResourceAsStream("icuLocales.txt"), - StandardCharsets.UTF_8)); + "UTF-8")); String id = null; while (null != (id = br.readLine())) { Locale result = Locale.forLanguageTag(id); - assertEquals(id, result.toLanguageTag(), "ulocale"); + assertEquals("ulocale", id, result.toLanguageTag()); } } @@ -292,151 +291,163 @@ public void testIcuLocales() throws Exception { public void testConstructor() { // all the old weirdness still holds, no new weirdness String[][] tests = { - // language to lower case, region to upper, variant unchanged - // short - {"X", "y", "z", "x", "Y"}, - // long - {"xXxXxXxXxXxX", "yYyYyYyYyYyYyYyY", "zZzZzZzZzZzZzZzZ", - "xxxxxxxxxxxx", "YYYYYYYYYYYYYYYY"}, - // mapped language ids - {"he", "IL", "", "he"}, - {"iw", "IL", "", "he"}, - {"yi", "DE", "", "yi"}, - {"ji", "DE", "", "yi"}, - {"id", "ID", "", "id"}, - {"in", "ID", "", "id"}, - // special variants - {"ja", "JP", "JP"}, - {"th", "TH", "TH"}, - {"no", "NO", "NY"}, - {"no", "NO", "NY"}, - // no canonicalization of 3-letter language codes - {"eng", "US", ""} + // language to lower case, region to upper, variant unchanged + // short + { "X", "y", "z", "x", "Y" }, + // long + { "xXxXxXxXxXxX", "yYyYyYyYyYyYyYyY", "zZzZzZzZzZzZzZzZ", + "xxxxxxxxxxxx", "YYYYYYYYYYYYYYYY" }, + // mapped language ids + { "he", "IL", "", "he" }, + { "iw", "IL", "", "he" }, + { "yi", "DE", "", "yi" }, + { "ji", "DE", "", "yi" }, + { "id", "ID", "", "id" }, + { "in", "ID", "", "id" }, + // special variants + { "ja", "JP", "JP" }, + { "th", "TH", "TH" }, + { "no", "NO", "NY" }, + { "no", "NO", "NY" }, + // no canonicalization of 3-letter language codes + { "eng", "US", "" } }; - for (int i = 0; i < tests.length; ++i) { + for (int i = 0; i < tests.length; ++ i) { String[] test = tests[i]; String id = String.valueOf(i); Locale locale = Locale.of(test[0], test[1], test[2]); - assertEquals(test.length > 3 ? test[3] : test[0], locale.getLanguage(), id + " lang"); - assertEquals(test.length > 4 ? test[4] : test[1], locale.getCountry(), id + " region"); - assertEquals(test.length > 5 ? test[5] : test[2], locale.getVariant(), id + " variant"); + assertEquals(id + " lang", test.length > 3 ? test[3] : test[0], locale.getLanguage()); + assertEquals(id + " region", test.length > 4 ? test[4] : test[1], locale.getCountry()); + assertEquals(id + " variant", test.length > 5 ? test[5] : test[2], locale.getVariant()); } } /// - /// Locale API Tests + /// Locale API tests. /// @Test public void testGetScript() { // forLanguageTag normalizes case Locale locale = Locale.forLanguageTag("und-latn"); - assertEquals("Latn", locale.getScript(), "forLanguageTag"); + assertEquals("forLanguageTag", "Latn", locale.getScript()); // Builder normalizes case locale = new Builder().setScript("LATN").build(); - assertEquals("Latn", locale.getScript(), "builder"); + assertEquals("builder", "Latn", locale.getScript()); // empty string is returned, not null, if there is no script locale = Locale.forLanguageTag("und"); - assertEquals("", locale.getScript(), "script is empty string"); + assertEquals("script is empty string", "", locale.getScript()); } @Test public void testGetExtension() { // forLanguageTag does NOT normalize to hyphen Locale locale = Locale.forLanguageTag("und-a-some_ex-tension"); - assertNull(locale.getExtension('a'), "some_ex-tension"); + assertEquals("some_ex-tension", null, locale.getExtension('a')); // regular extension locale = new Builder().setExtension('a', "some-ex-tension").build(); - assertEquals("some-ex-tension", locale.getExtension('a'), "builder"); + assertEquals("builder", "some-ex-tension", locale.getExtension('a')); // returns null if extension is not present - assertNull(locale.getExtension('b'), "empty b"); + assertEquals("empty b", null, locale.getExtension('b')); // throws exception if extension tag is illegal - assertThrows(IllegalArgumentException.class, () -> Locale.forLanguageTag("").getExtension('\uD800')); + new ExpectIAE() { public void call() { Locale.forLanguageTag("").getExtension('\uD800'); }}; // 'x' is not an extension, it's a private use tag, but it's accessed through this API locale = Locale.forLanguageTag("x-y-z-blork"); - assertEquals("y-z-blork", locale.getExtension('x'), "x"); + assertEquals("x", "y-z-blork", locale.getExtension('x')); } @Test public void testGetExtensionKeys() { Locale locale = Locale.forLanguageTag("und-a-xx-yy-b-zz-ww"); Set result = locale.getExtensionKeys(); - assertEquals(2, result.size(), "result size"); - assertTrue(result.contains('a') && result.contains('b'), "'a','b'"); + assertEquals("result size", 2, result.size()); + assertTrue("'a','b'", result.contains('a') && result.contains('b')); // result is not mutable - assertThrows(UnsupportedOperationException.class, () -> result.add('x')); + try { + result.add('x'); + fail("expected exception on add to extension key set"); + } + catch (UnsupportedOperationException e) { + // ok + } // returns empty set if no extensions locale = Locale.forLanguageTag("und"); - assertTrue(locale.getExtensionKeys().isEmpty(), "empty result"); + assertTrue("empty result", locale.getExtensionKeys().isEmpty()); } @Test public void testGetUnicodeLocaleAttributes() { Locale locale = Locale.forLanguageTag("en-US-u-abc-def"); Set attributes = locale.getUnicodeLocaleAttributes(); - assertEquals(2, attributes.size(), "number of attributes"); - assertTrue(attributes.contains("abc"), "attribute abc"); - assertTrue(attributes.contains("def"), "attribute def"); + assertEquals("number of attributes", 2, attributes.size()); + assertTrue("attribute abc", attributes.contains("abc")); + assertTrue("attribute def", attributes.contains("def")); locale = Locale.forLanguageTag("en-US-u-ca-gregory"); attributes = locale.getUnicodeLocaleAttributes(); - assertTrue(attributes.isEmpty(), "empty attributes"); + assertTrue("empty attributes", attributes.isEmpty()); } @Test public void testGetUnicodeLocaleType() { Locale locale = Locale.forLanguageTag("und-u-co-japanese-nu-thai"); - assertEquals("japanese", locale.getUnicodeLocaleType("co"), "collation"); - assertEquals("thai", locale.getUnicodeLocaleType("nu"), "numbers"); + assertEquals("collation", "japanese", locale.getUnicodeLocaleType("co")); + assertEquals("numbers", "thai", locale.getUnicodeLocaleType("nu")); // Unicode locale extension key is case insensitive - assertEquals("japanese", locale.getUnicodeLocaleType("Co"), "key case"); + assertEquals("key case", "japanese", locale.getUnicodeLocaleType("Co")); // if keyword is not present, returns null - assertNull(locale.getUnicodeLocaleType("xx"), "locale keyword not present"); + assertEquals("locale keyword not present", null, locale.getUnicodeLocaleType("xx")); // if no locale extension is set, returns null locale = Locale.forLanguageTag("und"); - assertNull(locale.getUnicodeLocaleType("co"), "locale extension not present"); + assertEquals("locale extension not present", null, locale.getUnicodeLocaleType("co")); // typeless keyword locale = Locale.forLanguageTag("und-u-kn"); - assertEquals("", locale.getUnicodeLocaleType("kn"), "typeless keyword"); + assertEquals("typeless keyword", "", locale.getUnicodeLocaleType("kn")); // invalid keys throw exception - assertThrows(IllegalArgumentException.class, () -> Locale.forLanguageTag("").getUnicodeLocaleType("q")); - assertThrows(IllegalArgumentException.class, () -> Locale.forLanguageTag("").getUnicodeLocaleType("abcdefghi")); + new ExpectIAE() { public void call() { Locale.forLanguageTag("").getUnicodeLocaleType("q"); }}; + new ExpectIAE() { public void call() { Locale.forLanguageTag("").getUnicodeLocaleType("abcdefghi"); }}; // null argument throws exception - assertThrows(NullPointerException.class, () -> Locale.forLanguageTag("").getUnicodeLocaleType(null)); + new ExpectNPE() { public void call() { Locale.forLanguageTag("").getUnicodeLocaleType(null); }}; } @Test public void testGetUnicodeLocaleKeys() { Locale locale = Locale.forLanguageTag("und-u-co-japanese-nu-thai"); Set result = locale.getUnicodeLocaleKeys(); - assertEquals(2, result.size(), "two keys"); - assertTrue(result.contains("co") && result.contains("nu"), "co and nu"); + assertEquals("two keys", 2, result.size()); + assertTrue("co and nu", result.contains("co") && result.contains("nu")); // result is not modifiable - assertThrows(UnsupportedOperationException.class, () -> result.add("frobozz")); + try { + result.add("frobozz"); + fail("expected exception when add to locale key set"); + } + catch (UnsupportedOperationException e) { + // ok + } } @Test public void testPrivateUseExtension() { Locale locale = Locale.forLanguageTag("x-y-x-blork-"); - assertEquals("y-x-blork", locale.getExtension(Locale.PRIVATE_USE_EXTENSION), "blork"); + assertEquals("blork", "y-x-blork", locale.getExtension(Locale.PRIVATE_USE_EXTENSION)); locale = Locale.forLanguageTag("und"); - assertNull(locale.getExtension(Locale.PRIVATE_USE_EXTENSION), "no privateuse"); + assertEquals("no privateuse", null, locale.getExtension(Locale.PRIVATE_USE_EXTENSION)); } @Test @@ -444,63 +455,63 @@ public void testToLanguageTag() { // lots of normalization to test here // test locales created using the constructor String[][] tests = { - // empty locale canonicalizes to 'und' - {"", "", "", "und"}, - // variant alone is not a valid Locale, but has a valid language tag - {"", "", "NewYork", "und-NewYork"}, - // standard valid locales - {"", "Us", "", "und-US"}, - {"", "US", "NewYork", "und-US-NewYork"}, - {"EN", "", "", "en"}, - {"EN", "", "NewYork", "en-NewYork"}, - {"EN", "US", "", "en-US"}, - {"EN", "US", "NewYork", "en-US-NewYork"}, - // underscore in variant will be emitted as multiple variant subtags - {"en", "US", "Newer_Yorker", "en-US-Newer-Yorker"}, - // invalid variant subtags are appended as private use - {"en", "US", "new_yorker", "en-US-x-lvariant-new-yorker"}, - // the first invalid variant subtags and following variant subtags are appended as private use - {"en", "US", "Windows_XP_Home", "en-US-Windows-x-lvariant-XP-Home"}, - // too long variant and following variant subtags disappear - {"en", "US", "WindowsVista_SP2", "en-US"}, - // invalid region subtag disappears - {"en", "USA", "", "en"}, - // invalid language tag disappears - {"e", "US", "", "und-US"}, - // three-letter language tags are not canonicalized - {"Eng", "", "", "eng"}, - // legacy languages canonicalize to modern equivalents - {"he", "IL", "", "he-IL"}, - {"iw", "IL", "", "he-IL"}, - {"yi", "DE", "", "yi-DE"}, - {"ji", "DE", "", "yi-DE"}, - {"id", "ID", "", "id-ID"}, - {"in", "ID", "", "id-ID"}, - // special values are converted on output - {"ja", "JP", "JP", "ja-JP-u-ca-japanese-x-lvariant-JP"}, - {"th", "TH", "TH", "th-TH-u-nu-thai-x-lvariant-TH"}, - {"no", "NO", "NY", "nn-NO"} + // empty locale canonicalizes to 'und' + { "", "", "", "und" }, + // variant alone is not a valid Locale, but has a valid language tag + { "", "", "NewYork", "und-NewYork" }, + // standard valid locales + { "", "Us", "", "und-US" }, + { "", "US", "NewYork", "und-US-NewYork" }, + { "EN", "", "", "en" }, + { "EN", "", "NewYork", "en-NewYork" }, + { "EN", "US", "", "en-US" }, + { "EN", "US", "NewYork", "en-US-NewYork" }, + // underscore in variant will be emitted as multiple variant subtags + { "en", "US", "Newer_Yorker", "en-US-Newer-Yorker" }, + // invalid variant subtags are appended as private use + { "en", "US", "new_yorker", "en-US-x-lvariant-new-yorker" }, + // the first invalid variant subtags and following variant subtags are appended as private use + { "en", "US", "Windows_XP_Home", "en-US-Windows-x-lvariant-XP-Home" }, + // too long variant and following variant subtags disappear + { "en", "US", "WindowsVista_SP2", "en-US" }, + // invalid region subtag disappears + { "en", "USA", "", "en" }, + // invalid language tag disappears + { "e", "US", "", "und-US" }, + // three-letter language tags are not canonicalized + { "Eng", "", "", "eng" }, + // legacy languages canonicalize to modern equivalents + { "he", "IL", "", "he-IL" }, + { "iw", "IL", "", "he-IL" }, + { "yi", "DE", "", "yi-DE" }, + { "ji", "DE", "", "yi-DE" }, + { "id", "ID", "", "id-ID" }, + { "in", "ID", "", "id-ID" }, + // special values are converted on output + { "ja", "JP", "JP", "ja-JP-u-ca-japanese-x-lvariant-JP" }, + { "th", "TH", "TH", "th-TH-u-nu-thai-x-lvariant-TH" }, + { "no", "NO", "NY", "nn-NO" } }; for (int i = 0; i < tests.length; ++i) { String[] test = tests[i]; Locale locale = Locale.of(test[0], test[1], test[2]); - assertEquals(test[3], locale.toLanguageTag(), "case " + i); + assertEquals("case " + i, test[3], locale.toLanguageTag()); } // test locales created from forLanguageTag String[][] tests1 = { - // case is normalized during the round trip - {"EN-us", "en-US"}, - {"en-Latn-US", "en-Latn-US"}, - // reordering Unicode locale extensions - {"de-u-co-phonebk-ca-gregory", "de-u-ca-gregory-co-phonebk"}, - // private use only language tag is preserved (no extra "und") - {"x-elmer", "x-elmer"}, - {"x-lvariant-JP", "x-lvariant-JP"}, + // case is normalized during the round trip + { "EN-us", "en-US" }, + { "en-Latn-US", "en-Latn-US" }, + // reordering Unicode locale extensions + { "de-u-co-phonebk-ca-gregory", "de-u-ca-gregory-co-phonebk" }, + // private use only language tag is preserved (no extra "und") + { "x-elmer", "x-elmer" }, + { "x-lvariant-JP", "x-lvariant-JP" }, }; for (String[] test : tests1) { Locale locale = Locale.forLanguageTag(test[0]); - assertEquals(test[1], locale.toLanguageTag(), "case " + test[0]); + assertEquals("case " + test[0], test[1], locale.toLanguageTag()); } } @@ -513,101 +524,102 @@ public void testForLanguageTag() { // sample private use tags) come from 4646bis Feb 29, 2009. String[][] tests = { - // private use tags only - {"x-abc", "x-abc"}, - {"x-a-b-c", "x-a-b-c"}, - {"x-a-12345678", "x-a-12345678"}, - - // legacy language tags with preferred mappings - {"i-ami", "ami"}, - {"i-bnn", "bnn"}, - {"i-hak", "hak"}, - {"i-klingon", "tlh"}, - {"i-lux", "lb"}, // two-letter tag - {"i-navajo", "nv"}, // two-letter tag - {"i-pwn", "pwn"}, - {"i-tao", "tao"}, - {"i-tay", "tay"}, - {"i-tsu", "tsu"}, - {"art-lojban", "jbo"}, - {"no-bok", "nb"}, - {"no-nyn", "nn"}, - {"sgn-BE-FR", "sfb"}, - {"sgn-BE-NL", "vgt"}, - {"sgn-CH-DE", "sgg"}, - {"zh-guoyu", "cmn"}, - {"zh-hakka", "hak"}, - {"zh-min-nan", "nan"}, - {"zh-xiang", "hsn"}, - - // irregular legacy language tags, no preferred mappings, drop illegal fields - // from end. If no subtag is mappable, fallback to 'und' - {"i-default", "en-x-i-default"}, - {"i-enochian", "x-i-enochian"}, - {"i-mingo", "see-x-i-mingo"}, - {"en-GB-oed", "en-GB-x-oed"}, - {"zh-min", "nan-x-zh-min"}, - {"cel-gaulish", "xtg-x-cel-gaulish"}, + // private use tags only + { "x-abc", "x-abc" }, + { "x-a-b-c", "x-a-b-c" }, + { "x-a-12345678", "x-a-12345678" }, + + // legacy language tags with preferred mappings + { "i-ami", "ami" }, + { "i-bnn", "bnn" }, + { "i-hak", "hak" }, + { "i-klingon", "tlh" }, + { "i-lux", "lb" }, // two-letter tag + { "i-navajo", "nv" }, // two-letter tag + { "i-pwn", "pwn" }, + { "i-tao", "tao" }, + { "i-tay", "tay" }, + { "i-tsu", "tsu" }, + { "art-lojban", "jbo" }, + { "no-bok", "nb" }, + { "no-nyn", "nn" }, + { "sgn-BE-FR", "sfb" }, + { "sgn-BE-NL", "vgt" }, + { "sgn-CH-DE", "sgg" }, + { "zh-guoyu", "cmn" }, + { "zh-hakka", "hak" }, + { "zh-min-nan", "nan" }, + { "zh-xiang", "hsn" }, + + // irregular legacy language tags, no preferred mappings, drop illegal fields + // from end. If no subtag is mappable, fallback to 'und' + { "i-default", "en-x-i-default" }, + { "i-enochian", "x-i-enochian" }, + { "i-mingo", "see-x-i-mingo" }, + { "en-GB-oed", "en-GB-x-oed" }, + { "zh-min", "nan-x-zh-min" }, + { "cel-gaulish", "xtg-x-cel-gaulish" }, }; for (int i = 0; i < tests.length; ++i) { String[] test = tests[i]; Locale locale = Locale.forLanguageTag(test[0]); - assertEquals(test[1], locale.toLanguageTag(), "legacy language tag case " + i); + assertEquals("legacy language tag case " + i, test[1], locale.toLanguageTag()); } // forLanguageTag ignores everything past the first place it encounters // a syntax error - tests = new String[][]{ - {"valid", - "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x-y-12345678-z", - "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x-y-12345678-z"}, - {"segment of private use tag too long", - "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x-y-123456789-z", - "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x-y"}, - {"segment of private use tag is empty", - "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x-y--12345678-z", - "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x-y"}, - {"first segment of private use tag is empty", - "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x--y-12345678-z", - "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def"}, - {"illegal extension tag", - "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-\uD800-y-12345678-z", - "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def"}, - {"locale subtag with no value", - "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-x-y-12345678-z", - "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-x-y-12345678-z"}, - {"locale key subtag invalid", - "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-123456789-def-x-y-12345678-z", - "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc"}, - // locale key subtag invalid in earlier position, all following subtags - // dropped (and so the locale extension dropped as well) - {"locale key subtag invalid in earlier position", - "en-US-Newer-Yorker-a-bb-cc-dd-u-123456789-abc-bb-def-x-y-12345678-z", - "en-US-Newer-Yorker-a-bb-cc-dd"}, + tests = new String[][] { + { "valid", + "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x-y-12345678-z", + "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x-y-12345678-z" }, + { "segment of private use tag too long", + "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x-y-123456789-z", + "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x-y" }, + { "segment of private use tag is empty", + "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x-y--12345678-z", + "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x-y" }, + { "first segment of private use tag is empty", + "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x--y-12345678-z", + "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def" }, + { "illegal extension tag", + "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-\uD800-y-12345678-z", + "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def" }, + { "locale subtag with no value", + "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-x-y-12345678-z", + "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-x-y-12345678-z" }, + { "locale key subtag invalid", + "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-123456789-def-x-y-12345678-z", + "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc" }, + // locale key subtag invalid in earlier position, all following subtags + // dropped (and so the locale extension dropped as well) + { "locale key subtag invalid in earlier position", + "en-US-Newer-Yorker-a-bb-cc-dd-u-123456789-abc-bb-def-x-y-12345678-z", + "en-US-Newer-Yorker-a-bb-cc-dd" }, }; for (int i = 0; i < tests.length; ++i) { String[] test = tests[i]; String msg = "syntax error case " + i + " " + test[0]; try { Locale locale = Locale.forLanguageTag(test[1]); - assertEquals(test[2], locale.toLanguageTag(), msg); - } catch (IllegalArgumentException e) { + assertEquals(msg, test[2], locale.toLanguageTag()); + } + catch (IllegalArgumentException e) { fail(msg + " caught exception: " + e); } } // duplicated extension are just ignored Locale locale = Locale.forLanguageTag("und-d-aa-00-bb-01-D-AA-10-cc-11-c-1234"); - assertEquals("aa-00-bb-01", locale.getExtension('d'), "extension"); - assertEquals("1234", locale.getExtension('c'), "extension c"); + assertEquals("extension", "aa-00-bb-01", locale.getExtension('d')); + assertEquals("extension c", "1234", locale.getExtension('c')); locale = Locale.forLanguageTag("und-U-ca-gregory-u-ca-japanese"); - assertEquals("ca-gregory", locale.getExtension(Locale.UNICODE_LOCALE_EXTENSION), "Unicode extension"); + assertEquals("Unicode extension", "ca-gregory", locale.getExtension(Locale.UNICODE_LOCALE_EXTENSION)); // redundant Unicode locale keys in an extension are ignored locale = Locale.forLanguageTag("und-u-aa-000-bb-001-bB-002-cc-003-c-1234"); - assertEquals("aa-000-bb-001-cc-003", locale.getExtension(Locale.UNICODE_LOCALE_EXTENSION), "Unicode keywords"); - assertEquals("1234", locale.getExtension('c'), "Duplicated Unicode locake key followed by an extension"); + assertEquals("Unicode keywords", "aa-000-bb-001-cc-003", locale.getExtension(Locale.UNICODE_LOCALE_EXTENSION)); + assertEquals("Duplicated Unicode locake key followed by an extension", "1234", locale.getExtension('c')); } @Test @@ -618,12 +630,12 @@ public void testGetDisplayScript() { Locale oldLocale = Locale.getDefault(); Locale.setDefault(Locale.US); - assertEquals("Latin", latnLocale.getDisplayScript(), "latn US"); - assertEquals("Simplified", hansLocale.getDisplayScript(), "hans US"); + assertEquals("latn US", "Latin", latnLocale.getDisplayScript()); + assertEquals("hans US", "Simplified", hansLocale.getDisplayScript()); Locale.setDefault(Locale.GERMANY); - assertEquals("Lateinisch", latnLocale.getDisplayScript(), "latn DE"); - assertEquals("Vereinfacht", hansLocale.getDisplayScript(), "hans DE"); + assertEquals("latn DE", "Lateinisch", latnLocale.getDisplayScript()); + assertEquals("hans DE", "Vereinfacht", hansLocale.getDisplayScript()); Locale.setDefault(oldLocale); } @@ -633,11 +645,11 @@ public void testGetDisplayScriptWithLocale() { Locale latnLocale = Locale.forLanguageTag("und-latn"); Locale hansLocale = Locale.forLanguageTag("und-hans"); - assertEquals("Latin", latnLocale.getDisplayScript(Locale.US), "latn US"); - assertEquals("Simplified", hansLocale.getDisplayScript(Locale.US), "hans US"); + assertEquals("latn US", "Latin", latnLocale.getDisplayScript(Locale.US)); + assertEquals("hans US", "Simplified", hansLocale.getDisplayScript(Locale.US)); - assertEquals("Lateinisch", latnLocale.getDisplayScript(Locale.GERMANY), "latn DE"); - assertEquals("Vereinfacht", hansLocale.getDisplayScript(Locale.GERMANY), "hans DE"); + assertEquals("latn DE", "Lateinisch", latnLocale.getDisplayScript(Locale.GERMANY)); + assertEquals("hans DE", "Vereinfacht", hansLocale.getDisplayScript(Locale.GERMANY)); } @Test @@ -683,10 +695,10 @@ public void testGetDisplayName() { for (int i = 0; i < testLocales.length; i++) { Locale loc = testLocales[i]; - assertEquals(displayNameEnglish[i], loc.getDisplayName(Locale.ENGLISH), - "English display name for " + loc.toLanguageTag()); - assertEquals(displayNameSimplifiedChinese[i], loc.getDisplayName(Locale.CHINA), - "Simplified Chinese display name for " + loc.toLanguageTag()); + assertEquals("English display name for " + loc.toLanguageTag(), + displayNameEnglish[i], loc.getDisplayName(Locale.ENGLISH)); + assertEquals("Simplified Chinese display name for " + loc.toLanguageTag(), + displayNameSimplifiedChinese[i], loc.getDisplayName(Locale.CHINA)); } } @@ -704,33 +716,37 @@ public void testBuilderSetLocale() { Locale locale = Locale.forLanguageTag(languageTag); Locale result = lenientBuilder - .setLocale(locale) - .build(); - assertEquals(target, result.toLanguageTag(), "long tag"); - assertEquals(locale, result, "long tag"); + .setLocale(locale) + .build(); + assertEquals("long tag", target, result.toLanguageTag()); + assertEquals("long tag", locale, result); // null is illegal - assertThrows(NullPointerException.class, () -> builder.setLocale(null), - "Setting null locale should throw NPE"); + new BuilderNPE("locale") { + public void call() { b.setLocale(null); } + }; // builder canonicalizes the three legacy locales: // ja_JP_JP, th_TH_TH, no_NY_NO. locale = builder.setLocale(Locale.of("ja", "JP", "JP")).build(); - assertEquals("ja-JP-u-ca-japanese", locale.toLanguageTag(), "ja_JP_JP languagetag"); - assertEquals("", locale.getVariant(), "ja_JP_JP variant"); + assertEquals("ja_JP_JP languagetag", "ja-JP-u-ca-japanese", locale.toLanguageTag()); + assertEquals("ja_JP_JP variant", "", locale.getVariant()); locale = builder.setLocale(Locale.of("th", "TH", "TH")).build(); - assertEquals("th-TH-u-nu-thai", locale.toLanguageTag(), "th_TH_TH languagetag"); - assertEquals("", locale.getVariant(), "th_TH_TH variant"); + assertEquals("th_TH_TH languagetag", "th-TH-u-nu-thai", locale.toLanguageTag()); + assertEquals("th_TH_TH variant", "", locale.getVariant()); locale = builder.setLocale(Locale.of("no", "NO", "NY")).build(); - assertEquals("nn-NO", locale.toLanguageTag(), "no_NO_NY languagetag"); - assertEquals("nn", locale.getLanguage(), "no_NO_NY language"); - assertEquals("", locale.getVariant(), "no_NO_NY variant"); + assertEquals("no_NO_NY languagetag", "nn-NO", locale.toLanguageTag()); + assertEquals("no_NO_NY language", "nn", locale.getLanguage()); + assertEquals("no_NO_NY variant", "", locale.getVariant()); // non-canonical, non-legacy locales are invalid - assertThrows(IllformedLocaleException.class, - () -> new Builder().setLocale(Locale.of("123", "4567", "89")), "123_4567_89"); + new BuilderILE("123_4567_89") { + public void call() { + b.setLocale(Locale.of("123", "4567", "89")); + } + }; } @Test @@ -739,20 +755,16 @@ public void testBuilderSetLanguageTag() { String target = "en-Latn-US-NewYork-a-xx-b-yy-x-1-2-3"; Builder builder = new Builder(); String result = builder - .setLanguageTag(source) - .build() - .toLanguageTag(); - assertEquals(target, result, "language"); - - // redundant extensions are ignored - assertEquals("und-a-xx-yy-b-ww-c-vv", - new Builder().setLanguageTag("und-a-xx-yy-b-ww-A-00-11-c-vv").build().toLanguageTag()); - // redundant Unicode locale extension keys are ignored - assertEquals("und-u-cu-usd-nu-thai-xx-1234", - new Builder().setLanguageTag("und-u-nu-thai-cu-usd-NU-chinese-xx-1234").build().toLanguageTag()); - // redundant Unicode locale extension attributes are ignored - assertEquals("und-u-bar-foo", - new Builder().setLanguageTag("und-u-foo-bar-FOO").build().toLanguageTag()); + .setLanguageTag(source) + .build() + .toLanguageTag(); + assertEquals("language", target, result); + + // redundant extensions cause a failure + new BuilderILE() { public void call() { b.setLanguageTag("und-a-xx-yy-b-ww-A-00-11-c-vv"); }}; + + // redundant Unicode locale extension keys within an Unicode locale extension cause a failure + new BuilderILE() { public void call() { b.setLanguageTag("und-u-nu-thai-NU-chinese-xx-1234"); }}; } // Test the values that should clear the builder @@ -764,9 +776,9 @@ public void testBuilderSetLanguageTagClear(String tag) { var bldr = new Builder(); bldr.setLanguageTag("en-US"); assertDoesNotThrow(() -> bldr.setLanguageTag(tag)); - assertEquals(empty.build(), bldr.build(), - "Setting a %s language tag did not clear the builder" - .formatted(tag == null ? "null" : "empty")); + assertEquals("Setting a %s language tag did not clear the builder" + .formatted(tag == null ? "null" : "empty"), + empty.build(), bldr.build()); } @Test @@ -777,18 +789,18 @@ public void testBuilderSetLanguage() { String defaulted = ""; Builder builder = new Builder(); String result = builder - .setLanguage(source) - .build() - .getLanguage(); - assertEquals(target, result, "en"); + .setLanguage(source) + .build() + .getLanguage(); + assertEquals("en", target, result); // setting with empty resets result = builder - .setLanguage(target) - .setLanguage("") - .build() - .getLanguage(); - assertEquals(defaulted, result, "empty"); + .setLanguage(target) + .setLanguage("") + .build() + .getLanguage(); + assertEquals("empty", defaulted, result); // setting with null resets too result = builder @@ -796,25 +808,23 @@ public void testBuilderSetLanguage() { .setLanguage(null) .build() .getLanguage(); - assertEquals(defaulted, result, "null"); + assertEquals("null", defaulted, result); // language codes must be 2-8 alpha // for forwards compatibility, 4-alpha and 5-8 alpha (registered) // languages are accepted syntax - for (String arg : List.of("q", "abcdefghi", "13")) { - assertThrows(IllformedLocaleException.class, () -> new Builder().setLanguage(arg)); - } + new BuilderILE("q", "abcdefghi", "13") { public void call() { b.setLanguage(arg); }}; // language code validation is NOT performed, any 2-8-alpha passes - assertNotNull(builder.setLanguage("zz").build(), "2alpha"); - assertNotNull(builder.setLanguage("abcdefgh").build(), "8alpha"); + assertNotNull("2alpha", builder.setLanguage("zz").build()); + assertNotNull("8alpha", builder.setLanguage("abcdefgh").build()); // three-letter language codes are NOT canonicalized to two-letter result = builder - .setLanguage("eng") - .build() - .getLanguage(); - assertEquals("eng", result, "eng"); + .setLanguage("eng") + .build() + .getLanguage(); + assertEquals("eng", "eng", result); } @Test @@ -825,18 +835,18 @@ public void testBuilderSetScript() { String defaulted = ""; Builder builder = new Builder(); String result = builder - .setScript(source) - .build() - .getScript(); - assertEquals(target, result, "script"); + .setScript(source) + .build() + .getScript(); + assertEquals("script", target, result); // setting with empty resets result = builder - .setScript(target) - .setScript("") - .build() - .getScript(); - assertEquals(defaulted, result, "empty"); + .setScript(target) + .setScript("") + .build() + .getScript(); + assertEquals("empty", defaulted, result); // settting with null also resets result = builder @@ -844,17 +854,14 @@ public void testBuilderSetScript() { .setScript(null) .build() .getScript(); - assertEquals(defaulted, result, "null"); + assertEquals("null", defaulted, result); // ill-formed script codes throw IAE // must be 4alpha - for (String arg : List.of("abc", "abcde", "l3tn")) { - assertThrows(IllformedLocaleException.class, () -> new Builder().setScript(arg)); - } - + new BuilderILE("abc", "abcde", "l3tn") { public void call() { b.setScript(arg); }}; // script code validation is NOT performed, any 4-alpha passes - assertEquals("Wxyz", builder.setScript("wxyz").build().getScript(), "4alpha"); + assertEquals("4alpha", "Wxyz", builder.setScript("wxyz").build().getScript()); } @Test @@ -865,18 +872,18 @@ public void testBuilderSetRegion() { String defaulted = ""; Builder builder = new Builder(); String result = builder - .setRegion(source) - .build() - .getCountry(); - assertEquals(target, result, "us"); + .setRegion(source) + .build() + .getCountry(); + assertEquals("us", target, result); // setting with empty resets result = builder - .setRegion(target) - .setRegion("") - .build() - .getCountry(); - assertEquals(defaulted, result, "empty"); + .setRegion(target) + .setRegion("") + .build() + .getCountry(); + assertEquals("empty", defaulted, result); // setting with null also resets result = builder @@ -884,17 +891,15 @@ public void testBuilderSetRegion() { .setRegion(null) .build() .getCountry(); - assertEquals(defaulted, result, "null"); + assertEquals("null", defaulted, result); // ill-formed region codes throw IAE // 2 alpha or 3 numeric - for (String arg : List.of("q", "abc", "12", "1234", "a3", "12a")) { - assertThrows(IllformedLocaleException.class, () -> new Builder().setRegion(arg)); - } + new BuilderILE("q", "abc", "12", "1234", "a3", "12a") { public void call() { b.setRegion(arg); }}; // region code validation is NOT performed, any 2-alpha or 3-digit passes - assertEquals("ZZ", builder.setRegion("ZZ").build().getCountry(), "2alpha"); - assertEquals("000", builder.setRegion("000").build().getCountry(), "3digit"); + assertEquals("2alpha", "ZZ", builder.setRegion("ZZ").build().getCountry()); + assertEquals("3digit", "000", builder.setRegion("000").build().getCountry()); } @Test @@ -905,31 +910,31 @@ public void testBuilderSetVariant() { String defaulted = ""; Builder builder = new Builder(); String result = builder - .setVariant(source) - .build() - .getVariant(); - assertEquals(target, result, "NewYork"); + .setVariant(source) + .build() + .getVariant(); + assertEquals("NewYork", target, result); result = builder - .setVariant("NeWeR_YoRkEr") - .build() - .toLanguageTag(); - assertEquals("und-NeWeR-YoRkEr", result, "newer yorker"); + .setVariant("NeWeR_YoRkEr") + .build() + .toLanguageTag(); + assertEquals("newer yorker", "und-NeWeR-YoRkEr", result); // subtags of variant are NOT reordered result = builder - .setVariant("zzzzz_yyyyy_xxxxx") - .build() - .getVariant(); - assertEquals("zzzzz_yyyyy_xxxxx", result, "zyx"); + .setVariant("zzzzz_yyyyy_xxxxx") + .build() + .getVariant(); + assertEquals("zyx", "zzzzz_yyyyy_xxxxx", result); // setting to empty resets result = builder - .setVariant(target) - .setVariant("") - .build() - .getVariant(); - assertEquals(defaulted, result, "empty"); + .setVariant(target) + .setVariant("") + .build() + .getVariant(); + assertEquals("empty", defaulted, result); // setting to null also resets result = builder @@ -937,21 +942,17 @@ public void testBuilderSetVariant() { .setVariant(null) .build() .getVariant(); - assertEquals(defaulted, result, "null"); + assertEquals("null", defaulted, result); // ill-formed variants throw IAE // digit followed by 3-7 characters, or alpha followed by 4-8 characters. - for (String arg : List.of("abcd", "abcdefghi", "1ab", "1abcdefgh")) { - assertThrows(IllformedLocaleException.class, () -> new Builder().setVariant(arg)); - } - + new BuilderILE("abcd", "abcdefghi", "1ab", "1abcdefgh") { public void call() { b.setVariant(arg); }}; // 4 characters is ok as long as the first is a digit - assertEquals("1abc", builder.setVariant("1abc").build().getVariant(), "digit+3alpha"); + assertEquals("digit+3alpha", "1abc", builder.setVariant("1abc").build().getVariant()); // all subfields must conform - assertThrows(IllformedLocaleException.class, () -> new Builder().setVariant("abcde-fg")); - + new BuilderILE("abcde-fg") { public void call() { b.setVariant(arg); }}; } @Test @@ -962,18 +963,18 @@ public void testBuilderSetExtension() { String target = "ab-abcdefgh-12-12345678"; Builder builder = new Builder(); String result = builder - .setExtension(sourceKey, sourceValue) - .build() - .getExtension(sourceKey); - assertEquals(target, result, "extension"); + .setExtension(sourceKey, sourceValue) + .build() + .getExtension(sourceKey); + assertEquals("extension", target, result); // setting with empty resets result = builder - .setExtension(sourceKey, sourceValue) - .setExtension(sourceKey, "") - .build() - .getExtension(sourceKey); - assertNull(result, "empty"); + .setExtension(sourceKey, sourceValue) + .setExtension(sourceKey, "") + .build() + .getExtension(sourceKey); + assertEquals("empty", null, result); // setting with null also resets result = builder @@ -981,120 +982,100 @@ public void testBuilderSetExtension() { .setExtension(sourceKey, null) .build() .getExtension(sourceKey); - assertNull(result, "null"); + assertEquals("null", null, result); // ill-formed extension keys throw IAE // must be in [0-9a-ZA-Z] - assertThrows(IllformedLocaleException.class, - () -> new Builder().setExtension('$', sourceValue)); - + new BuilderILE("$") { public void call() { b.setExtension('$', sourceValue); }}; // each segment of value must be 2-8 alphanum - assertThrows(IllformedLocaleException.class, - () -> new Builder().setExtension(sourceKey, "ab-cd-123456789")); - + new BuilderILE("ab-cd-123456789") { public void call() { b.setExtension(sourceKey, arg); }}; // no multiple hyphens. - assertThrows(IllformedLocaleException.class, - () -> new Builder().setExtension(sourceKey, "ab--cd")); - + new BuilderILE("ab--cd") { public void call() { b.setExtension(sourceKey, arg); }}; // locale extension key has special handling Locale locale = builder - .setExtension('u', "co-japanese") - .build(); - assertEquals("japanese", locale.getUnicodeLocaleType("co"), "locale extension"); + .setExtension('u', "co-japanese") + .build(); + assertEquals("locale extension", "japanese", locale.getUnicodeLocaleType("co")); // locale extension has same behavior with set locale keyword Locale locale2 = builder - .setUnicodeLocaleKeyword("co", "japanese") - .build(); - assertEquals(locale, locale2, "locales with extension"); + .setUnicodeLocaleKeyword("co", "japanese") + .build(); + assertEquals("locales with extension", locale, locale2); // setting locale extension overrides all previous calls to setLocaleKeyword Locale locale3 = builder - .setExtension('u', "xxx-nu-thai") - .build(); - assertNull(locale3.getUnicodeLocaleType("co"), "remove co"); - assertEquals("thai", locale3.getUnicodeLocaleType("nu"), "override thai"); - assertEquals(1, locale3.getUnicodeLocaleAttributes().size(), "override attribute"); + .setExtension('u', "xxx-nu-thai") + .build(); + assertEquals("remove co", null, locale3.getUnicodeLocaleType("co")); + assertEquals("override thai", "thai", locale3.getUnicodeLocaleType("nu")); + assertEquals("override attribute", 1, locale3.getUnicodeLocaleAttributes().size()); // setting locale keyword extends values already set by the locale extension Locale locale4 = builder - .setUnicodeLocaleKeyword("co", "japanese") - .build(); - assertEquals("japanese", locale4.getUnicodeLocaleType("co"), "extend"); - assertEquals("thai", locale4.getUnicodeLocaleType("nu"), "extend"); + .setUnicodeLocaleKeyword("co", "japanese") + .build(); + assertEquals("extend", "japanese", locale4.getUnicodeLocaleType("co")); + assertEquals("extend", "thai", locale4.getUnicodeLocaleType("nu")); // locale extension subtags are reordered result = builder - .clear() - .setExtension('u', "456-123-zz-123-yy-456-xx-789") - .build() - .toLanguageTag(); - assertEquals("und-u-123-456-xx-789-yy-456-zz-123", result, "reorder"); + .clear() + .setExtension('u', "456-123-zz-123-yy-456-xx-789") + .build() + .toLanguageTag(); + assertEquals("reorder", "und-u-123-456-xx-789-yy-456-zz-123", result); // multiple keyword types result = builder - .clear() - .setExtension('u', "nu-thai-foobar") - .build() - .getUnicodeLocaleType("nu"); - assertEquals("thai-foobar", result, "multiple types"); + .clear() + .setExtension('u', "nu-thai-foobar") + .build() + .getUnicodeLocaleType("nu"); + assertEquals("multiple types", "thai-foobar", result); // redundant locale extensions are ignored result = builder - .clear() - .setExtension('u', "nu-thai-NU-chinese-xx-1234") - .build() - .toLanguageTag(); - assertEquals("und-u-nu-thai-xx-1234", result, "duplicate keys"); - - // redundant locale attributes are ignored - result = builder - .clear() - .setExtension('u', "posix-posix") - .build() - .toLanguageTag(); - assertEquals("und-u-posix", result, "duplicate attributes"); + .clear() + .setExtension('u', "nu-thai-NU-chinese-xx-1234") + .build() + .toLanguageTag(); + assertEquals("duplicate keys", "und-u-nu-thai-xx-1234", result); } @Test public void testBuilderAddUnicodeLocaleAttribute() { Builder builder = new Builder(); Locale locale = builder - .addUnicodeLocaleAttribute("def") - .addUnicodeLocaleAttribute("abc") - .build(); + .addUnicodeLocaleAttribute("def") + .addUnicodeLocaleAttribute("abc") + .build(); Set uattrs = locale.getUnicodeLocaleAttributes(); - assertEquals(2, uattrs.size(), "number of attributes"); - assertTrue(uattrs.contains("abc"), "attribute abc"); - assertTrue(uattrs.contains("def"), "attribute def"); + assertEquals("number of attributes", 2, uattrs.size()); + assertTrue("attribute abc", uattrs.contains("abc")); + assertTrue("attribute def", uattrs.contains("def")); // remove attribute locale = builder.removeUnicodeLocaleAttribute("xxx") - .build(); + .build(); - uattrs = locale.getUnicodeLocaleAttributes(); - assertEquals(2, uattrs.size(), "remove bogus"); + assertEquals("remove bogus", 2, uattrs.size()); // add duplicate locale = builder.addUnicodeLocaleAttribute("abc") - .build(); - uattrs = locale.getUnicodeLocaleAttributes(); - assertEquals(2, uattrs.size(), "add duplicate"); + .build(); + assertEquals("add duplicate", 2, uattrs.size()); // null attribute throws NPE - assertThrows(NullPointerException.class, - () -> new Builder().addUnicodeLocaleAttribute(null), "null attribute"); - - assertThrows(NullPointerException.class, - () -> new Builder().removeUnicodeLocaleAttribute(null), "null attribute removal"); + new BuilderNPE("null attribute") { public void call() { b.addUnicodeLocaleAttribute(null); }}; + new BuilderNPE("null attribute removal") { public void call() { b.removeUnicodeLocaleAttribute(null); }}; // illformed attribute throws IllformedLocaleException - assertThrows(IllformedLocaleException.class, - () -> new Builder().addUnicodeLocaleAttribute("ca"), "invalid attribute"); + new BuilderILE("invalid attribute") { public void call() { b.addUnicodeLocaleAttribute("ca"); }}; } @Test @@ -1102,51 +1083,43 @@ public void testBuildersetUnicodeLocaleKeyword() { // Note: most behavior is tested in testBuilderSetExtension Builder builder = new Builder(); Locale locale = builder - .setUnicodeLocaleKeyword("co", "japanese") - .setUnicodeLocaleKeyword("nu", "thai") - .build(); - assertEquals("japanese", locale.getUnicodeLocaleType("co"), "co"); - assertEquals("thai", locale.getUnicodeLocaleType("nu"), "nu"); - assertEquals(2, locale.getUnicodeLocaleKeys().size(), "keys"); + .setUnicodeLocaleKeyword("co", "japanese") + .setUnicodeLocaleKeyword("nu", "thai") + .build(); + assertEquals("co", "japanese", locale.getUnicodeLocaleType("co")); + assertEquals("nu", "thai", locale.getUnicodeLocaleType("nu")); + assertEquals("keys", 2, locale.getUnicodeLocaleKeys().size()); // can clear a keyword by setting to null, others remain String result = builder - .setUnicodeLocaleKeyword("co", null) - .build() - .toLanguageTag(); - assertEquals("und-u-nu-thai", result, "empty co"); + .setUnicodeLocaleKeyword("co", null) + .build() + .toLanguageTag(); + assertEquals("empty co", "und-u-nu-thai", result); // locale keyword extension goes when all keywords are gone result = builder - .setUnicodeLocaleKeyword("nu", null) - .build() - .toLanguageTag(); - assertEquals("und", result, "empty nu"); + .setUnicodeLocaleKeyword("nu", null) + .build() + .toLanguageTag(); + assertEquals("empty nu", "und", result); // locale keywords are ordered independent of order of addition result = builder - .setUnicodeLocaleKeyword("zz", "012") - .setUnicodeLocaleKeyword("aa", "345") - .build() - .toLanguageTag(); - assertEquals("und-u-aa-345-zz-012", result, "reordered"); + .setUnicodeLocaleKeyword("zz", "012") + .setUnicodeLocaleKeyword("aa", "345") + .build() + .toLanguageTag(); + assertEquals("reordered", "und-u-aa-345-zz-012", result); // null keyword throws NPE - assertThrows(NullPointerException.class, - () -> new Builder().setUnicodeLocaleKeyword(null, "thai"), "keyword"); - + new BuilderNPE("keyword") { public void call() { b.setUnicodeLocaleKeyword(null, "thai"); }}; // well-formed keywords are two alphanum - for (String arg : List.of("a", "abc")) { - assertThrows(IllformedLocaleException.class, - () -> new Builder().setUnicodeLocaleKeyword(arg, "value")); - } + new BuilderILE("a", "abc") { public void call() { b.setUnicodeLocaleKeyword(arg, "value"); }}; // well-formed values are 3-8 alphanum - for (String arg : List.of("ab", "abcdefghi")) { - assertThrows(IllformedLocaleException.class, - () -> new Builder().setUnicodeLocaleKeyword("ab", arg)); - } + new BuilderILE("ab", "abcdefghi") { public void call() { b.setUnicodeLocaleKeyword("ab", arg); }}; } @Test @@ -1156,15 +1129,13 @@ public void testBuilderPrivateUseExtension() { String target = "c-b-a"; Builder builder = new Builder(); String result = builder - .setExtension(Locale.PRIVATE_USE_EXTENSION, source) - .build() - .getExtension(Locale.PRIVATE_USE_EXTENSION); - assertEquals(target, result, "abc"); + .setExtension(Locale.PRIVATE_USE_EXTENSION, source) + .build() + .getExtension(Locale.PRIVATE_USE_EXTENSION); + assertEquals("abc", target, result); // multiple hyphens are ill-formed - assertThrows(IllformedLocaleException.class, - () -> new Builder().setExtension(Locale.PRIVATE_USE_EXTENSION, "a--b"), - "multiple-hyphens should throw IAE"); + new BuilderILE("a--b") { public void call() { b.setExtension(Locale.PRIVATE_USE_EXTENSION, arg); }}; } @Test @@ -1173,11 +1144,11 @@ public void testBuilderClear() { Builder builder = new Builder(); Locale locale = Locale.forLanguageTag(monster); String result = builder - .setLocale(locale) - .clear() - .build() - .toLanguageTag(); - assertEquals("und", result, "clear"); + .setLocale(locale) + .clear() + .build() + .toLanguageTag(); + assertEquals("clear", "und", result); } @Test @@ -1193,33 +1164,33 @@ public void testBuilderBuild() { @Test public void testSerialize() { final Locale[] testLocales = { - Locale.ROOT, - Locale.ENGLISH, - Locale.US, - Locale.of("en", "US", "Win"), - Locale.of("en", "US", "Win_XP"), - Locale.JAPAN, - Locale.of("ja", "JP", "JP"), - Locale.of("th", "TH"), - Locale.of("th", "TH", "TH"), - Locale.of("no", "NO"), - Locale.of("nb", "NO"), - Locale.of("nn", "NO"), - Locale.of("no", "NO", "NY"), - Locale.of("nn", "NO", "NY"), - Locale.of("he", "IL"), - Locale.of("he", "IL", "var"), - Locale.of("Language", "Country", "Variant"), - Locale.of("", "US"), - Locale.of("", "", "Java"), - Locale.forLanguageTag("en-Latn-US"), - Locale.forLanguageTag("zh-Hans"), - Locale.forLanguageTag("zh-Hant-TW"), - Locale.forLanguageTag("ja-JP-u-ca-japanese"), - Locale.forLanguageTag("und-Hant"), - Locale.forLanguageTag("und-a-123-456"), - Locale.forLanguageTag("en-x-java"), - Locale.forLanguageTag("th-TH-u-ca-buddist-nu-thai-x-lvariant-TH"), + Locale.ROOT, + Locale.ENGLISH, + Locale.US, + Locale.of("en", "US", "Win"), + Locale.of("en", "US", "Win_XP"), + Locale.JAPAN, + Locale.of("ja", "JP", "JP"), + Locale.of("th", "TH"), + Locale.of("th", "TH", "TH"), + Locale.of("no", "NO"), + Locale.of("nb", "NO"), + Locale.of("nn", "NO"), + Locale.of("no", "NO", "NY"), + Locale.of("nn", "NO", "NY"), + Locale.of("he", "IL"), + Locale.of("he", "IL", "var"), + Locale.of("Language", "Country", "Variant"), + Locale.of("", "US"), + Locale.of("", "", "Java"), + Locale.forLanguageTag("en-Latn-US"), + Locale.forLanguageTag("zh-Hans"), + Locale.forLanguageTag("zh-Hant-TW"), + Locale.forLanguageTag("ja-JP-u-ca-japanese"), + Locale.forLanguageTag("und-Hant"), + Locale.forLanguageTag("und-a-123-456"), + Locale.forLanguageTag("en-x-java"), + Locale.forLanguageTag("th-TH-u-ca-buddist-nu-thai-x-lvariant-TH"), }; for (Locale locale : testLocales) { @@ -1234,7 +1205,7 @@ public void testSerialize() { ObjectInputStream ois = new ObjectInputStream(bis); Object o = ois.readObject(); - assertEquals(locale, o, "roundtrip " + locale); + assertEquals("roundtrip " + locale, locale, o); } catch (Exception e) { fail(locale + " encountered exception:" + e.getLocalizedMessage()); } @@ -1260,9 +1231,11 @@ public void testDeserialize6() { } if (dataDir == null) { - fail("'dataDir' is null. serialized.data.dir Property value is " + dataDirName); + fail("'dataDir' is null. serialized.data.dir Property value is "+dataDirName); + return; } else if (!dataDir.isDirectory()) { - fail("'dataDir' is not a directory. dataDir: " + dataDir.toString()); + fail("'dataDir' is not a directory. dataDir: "+dataDir.toString()); + return; } File[] files = dataDir.listFiles(); @@ -1288,9 +1261,10 @@ public void testDeserialize6() { // deserialize try (FileInputStream fis = new FileInputStream(testfile); - ObjectInputStream ois = new ObjectInputStream(fis)) { + ObjectInputStream ois = new ObjectInputStream(fis)) + { Object o = ois.readObject(); - assertEquals(o, locale, "Deserialize Java 6 Locale " + locale); + assertEquals("Deserialize Java 6 Locale " + locale, o, locale); } catch (Exception e) { fail("Exception while reading " + testfile.getAbsolutePath() + " - " + e.getMessage()); } @@ -1310,15 +1284,15 @@ public void testBug7002320() { // extension "nu-thai". // String[][] testdata = { - {"ja-JP-x-lvariant-JP", "ja-JP-u-ca-japanese-x-lvariant-JP"}, // special case 1 - {"ja-JP-x-lvariant-JP-XXX"}, - {"ja-JP-u-ca-japanese-x-lvariant-JP"}, - {"ja-JP-u-ca-gregory-x-lvariant-JP"}, - {"ja-JP-u-cu-jpy-x-lvariant-JP"}, - {"ja-x-lvariant-JP"}, - {"th-TH-x-lvariant-TH", "th-TH-u-nu-thai-x-lvariant-TH"}, // special case 2 - {"th-TH-u-nu-thai-x-lvariant-TH"}, - {"en-US-x-lvariant-JP"}, + {"ja-JP-x-lvariant-JP", "ja-JP-u-ca-japanese-x-lvariant-JP"}, // special case 1 + {"ja-JP-x-lvariant-JP-XXX"}, + {"ja-JP-u-ca-japanese-x-lvariant-JP"}, + {"ja-JP-u-ca-gregory-x-lvariant-JP"}, + {"ja-JP-u-cu-jpy-x-lvariant-JP"}, + {"ja-x-lvariant-JP"}, + {"th-TH-x-lvariant-TH", "th-TH-u-nu-thai-x-lvariant-TH"}, // special case 2 + {"th-TH-u-nu-thai-x-lvariant-TH"}, + {"en-US-x-lvariant-JP"}, }; Builder bldr = new Builder(); @@ -1330,22 +1304,22 @@ public void testBug7002320() { // forLanguageTag Locale loc = Locale.forLanguageTag(in); String out = loc.toLanguageTag(); - assertEquals(expected, out, "Language tag roundtrip by forLanguageTag with input: " + in); + assertEquals("Language tag roundtrip by forLanguageTag with input: " + in, expected, out); // setLanguageTag bldr.clear(); bldr.setLanguageTag(in); loc = bldr.build(); out = loc.toLanguageTag(); - assertEquals(expected, out, "Language tag roundtrip by Builder.setLanguageTag with input: " + in); + assertEquals("Language tag roundtrip by Builder.setLanguageTag with input: " + in, expected, out); } } @Test public void testBug7023613() { String[][] testdata = { - {"en-Latn", "en__#Latn"}, - {"en-u-ca-japanese", "en__#u-ca-japanese"}, + {"en-Latn", "en__#Latn"}, + {"en-u-ca-japanese", "en__#u-ca-japanese"}, }; for (String[] data : testdata) { @@ -1354,7 +1328,7 @@ public void testBug7023613() { Locale loc = Locale.forLanguageTag(in); String out = loc.toString(); - assertEquals(expected, out, "Empty country field with non-empty script/extension with input: " + in); + assertEquals("Empty country field with non-empty script/extension with input: " + in, expected, out); } } @@ -1368,7 +1342,7 @@ public void testBug7033504() { checkCalendar(Locale.of("ja", "JP", "JP"), "java.util.JapaneseImperialCalendar"); checkCalendar(Locale.of("ja", "jp", "JP"), "java.util.JapaneseImperialCalendar"); checkCalendar(Locale.forLanguageTag("en-u-ca-japanese"), - "java.util.JapaneseImperialCalendar"); + "java.util.JapaneseImperialCalendar"); checkDigit(Locale.of("th", "TH", "th"), '0'); checkDigit(Locale.of("th", "th", "th"), '0'); @@ -1379,12 +1353,151 @@ public void testBug7033504() { private void checkCalendar(Locale loc, String expected) { Calendar cal = Calendar.getInstance(loc); - assertEquals(expected, cal.getClass().getName(), "Wrong calendar"); + assertEquals("Wrong calendar", expected, cal.getClass().getName()); } private void checkDigit(Locale loc, Character expected) { DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(loc); Character zero = dfs.getZeroDigit(); - assertEquals(expected, zero, "Wrong digit zero char"); + assertEquals("Wrong digit zero char", expected, zero); + } + + /// + /// utility asserts + /// + + private void assertTrue(String msg, boolean v) { + if (!v) { + fail(msg + ": expected true"); + } + } + + private void assertFalse(String msg, boolean v) { + if (v) { + fail(msg + ": expected false"); + } + } + + private void assertEquals(String msg, Object e, Object v) { + if (e == null ? v != null : !e.equals(v)) { + if (e != null) { + e = "'" + e + "'"; + } + if (v != null) { + v = "'" + v + "'"; + } + fail(msg + ": expected " + e + " but got " + v); + } + } + + private void assertNotEquals(String msg, Object e, Object v) { + if (e == null ? v == null : e.equals(v)) { + if (e != null) { + e = "'" + e + "'"; + } + fail(msg + ": expected not equal " + e); + } + } + + private void assertNull(String msg, Object o) { + if (o != null) { + fail(msg + ": expected null but got '" + o + "'"); + } + } + + private void assertNotNull(String msg, Object o) { + if (o == null) { + fail(msg + ": expected non null"); + } + } + + // not currently used, might get rid of exceptions from the API + private abstract class ExceptionTest { + private final Class exceptionClass; + + ExceptionTest(Class exceptionClass) { + this.exceptionClass = exceptionClass; + } + + public void run() { + String failMsg = null; + try { + call(); + failMsg = "expected " + exceptionClass.getName() + " but no exception thrown."; + } + catch (Exception e) { + if (!exceptionClass.isAssignableFrom(e.getClass())) { + failMsg = "expected " + exceptionClass.getName() + " but caught " + e; + } + } + if (failMsg != null) { + String msg = message(); + msg = msg == null ? "" : msg + " "; + fail(msg + failMsg); + } + } + + public String message() { + return null; + } + + public abstract void call(); + } + + private abstract class ExpectNPE extends ExceptionTest { + ExpectNPE() { + super(NullPointerException.class); + run(); + } + } + + private abstract class BuilderNPE extends ExceptionTest { + protected final String msg; + protected final Builder b = new Builder(); + + BuilderNPE(String msg) { + super(NullPointerException.class); + + this.msg = msg; + + run(); + } + + public String message() { + return msg; + } + } + + private abstract class ExpectIAE extends ExceptionTest { + ExpectIAE() { + super(IllegalArgumentException.class); + run(); + } + } + + private abstract class BuilderILE extends ExceptionTest { + protected final String[] args; + protected final Builder b = new Builder(); + + protected String arg; // mutates during call + + BuilderILE(String... args) { + super(IllformedLocaleException.class); + + this.args = args; + + run(); + } + + public void run() { + for (String arg : args) { + this.arg = arg; + super.run(); + } + } + + public String message() { + return "arg: '" + arg + "'"; + } } } diff --git a/test/jdk/java/util/concurrent/locks/Lock/OOMEInAQS.java b/test/jdk/java/util/concurrent/locks/Lock/OOMEInAQS.java index 0ed76f4b88504..aee6c3617c896 100644 --- a/test/jdk/java/util/concurrent/locks/Lock/OOMEInAQS.java +++ b/test/jdk/java/util/concurrent/locks/Lock/OOMEInAQS.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,7 +39,6 @@ * @bug 8066859 * @summary Check that AQS-based locks, conditions, and CountDownLatches do not fail when encountering OOME * @requires vm.gc.G1 - * @requires test.thread.factory == null * @requires !(vm.graal.enabled & vm.compMode == "Xcomp") * @run main/othervm -XX:+UseG1GC -XX:-UseGCOverheadLimit -Xmx48M -XX:-UseTLAB OOMEInAQS */ diff --git a/test/jdk/java/util/concurrent/tck/CompletableFutureTest.java b/test/jdk/java/util/concurrent/tck/CompletableFutureTest.java index fc86936d5da3c..de3d1dd1050bc 100644 --- a/test/jdk/java/util/concurrent/tck/CompletableFutureTest.java +++ b/test/jdk/java/util/concurrent/tck/CompletableFutureTest.java @@ -58,7 +58,6 @@ import java.util.concurrent.Executor; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinTask; -import java.util.concurrent.ForkJoinWorkerThread; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; @@ -5134,46 +5133,4 @@ public void testDefaultExceptionallyComposeAsyncExecutor_actionFailed() { checkCompletedWithWrappedException(g.toCompletableFuture(), r.ex); r.assertInvoked(); }} - - public void testOnlyHelpsIfInTheSamePool() throws Exception { - class Logic { - interface Extractor { ForkJoinPool pool(CompletableFuture cf) throws Exception; } - static final List executeInnerOuter( - ForkJoinPool outer, ForkJoinPool inner, Logic.Extractor extractor - ) throws Exception { - return CompletableFuture.supplyAsync(() -> - Stream.iterate(1, i -> i + 1) - .limit(64) - .map(i -> CompletableFuture.supplyAsync( - () -> Thread.currentThread() instanceof ForkJoinWorkerThread wt ? wt.getPool() : null, inner) - ) - .map(cf -> { - try { - return extractor.pool(cf); - } catch (Exception ex) { - throw new AssertionError("Unexpected", ex); - } - }) - .toList() - , outer).join(); - } - } - - List extractors = - List.of( - c -> c.get(60, SECONDS), - CompletableFuture::get, - CompletableFuture::join - ); - - try (var pool = new ForkJoinPool(2)) { - for (var extractor : extractors) { - for (var p : Logic.executeInnerOuter(pool, ForkJoinPool.commonPool(), extractor)) - assertTrue(p != pool); // The inners should have all been executed by commonPool - - for (var p : Logic.executeInnerOuter(pool, pool, extractor)) - assertTrue(p == pool); // The inners could have been helped by the outer - } - } - } } diff --git a/test/jdk/javax/net/ssl/ServerName/SSLSocketSNISensitive.java b/test/jdk/javax/net/ssl/ServerName/SSLSocketSNISensitive.java index fd1569b4eeafd..45593b9129e7c 100644 --- a/test/jdk/javax/net/ssl/ServerName/SSLSocketSNISensitive.java +++ b/test/jdk/javax/net/ssl/ServerName/SSLSocketSNISensitive.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, 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,7 +30,6 @@ * @test * @bug 7068321 * @summary Support TLS Server Name Indication (SNI) Extension in JSSE Server - * @enablePreview * @run main/othervm SSLSocketSNISensitive PKIX www.example.com * @run main/othervm SSLSocketSNISensitive SunX509 www.example.com * @run main/othervm SSLSocketSNISensitive PKIX www.example.net @@ -39,31 +38,19 @@ * @run main/othervm SSLSocketSNISensitive SunX509 www.invalid.com */ -import java.io.InputStream; -import java.io.OutputStream; -import java.security.PEMDecoder; -import java.security.PEMEncoder; -import java.security.interfaces.RSAPrivateKey; -import java.security.spec.PKCS8EncodedKeySpec; -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SNIHostName; -import javax.net.ssl.SNIServerName; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLParameters; -import javax.net.ssl.SSLServerSocket; -import javax.net.ssl.SSLServerSocketFactory; -import javax.net.ssl.SSLSession; -import javax.net.ssl.SSLSocket; -import javax.net.ssl.SSLSocketFactory; -import javax.net.ssl.TrustManagerFactory; +import java.net.*; +import java.util.*; +import java.io.*; +import javax.net.ssl.*; import java.security.Security; import java.security.KeyStore; import java.security.KeyFactory; import java.security.cert.Certificate; import java.security.cert.X509Certificate; -import java.util.ArrayList; +import java.security.cert.CertificateFactory; +import java.security.spec.*; +import java.security.interfaces.*; import java.util.Base64; -import java.util.List; // Note: this test case works only on TLS 1.2 and prior versions because of // the use of MD5withRSA signed certificate. @@ -87,167 +74,159 @@ public class SSLSocketSNISensitive { */ // Certificates and key used in the test. static String trustedCertStr = - "-----BEGIN CERTIFICATE-----\n" + - "MIICkjCCAfugAwIBAgIBADANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" + - "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" + - "MTIwNDE3MTIwNjA3WhcNMzMwMzI4MTIwNjA3WjA7MQswCQYDVQQGEwJVUzENMAsG\n" + - "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwgZ8wDQYJ\n" + - "KoZIhvcNAQEBBQADgY0AMIGJAoGBANY+7Enp+1S566kLcKk+qe4Ki6BxaHGZ+v7r\n" + - "vLksx9IQZCbAEf4YLbrZhKzKD3SPIJXyxPFwknAknIh3Knk8mViOZks7T8L3GnJr\n" + - "TBaVvDyTzDJum/QYiahfO2qpfN/Oya2UILmqsBAeLyWpzbQsAyWBXfoUtkOUgnzK\n" + - "fk6QAKYrAgMBAAGjgaUwgaIwHQYDVR0OBBYEFEtmQi7jT1ijXOafPsfkrLwSVu9e\n" + - "MGMGA1UdIwRcMFqAFEtmQi7jT1ijXOafPsfkrLwSVu9eoT+kPTA7MQswCQYDVQQG\n" + - "EwJVUzENMAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2\n" + - "Y2WCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEE\n" + - "BQADgYEAkKWxMc4+ODk5WwLXXweB8/IKfVfrizNn0KLEgsZ6xNXFIXDpiPGAFcgl\n" + - "MzFO424JgyvUulsUc/X16Cnuwwntkk6KUG7vEV7h4o9sAV7Cax3gfQE/EZFb4ybn\n" + - "aBm1UsujMKd/ovqbbbxJbmOWzCeo0QfIGleDEyh3NBBZ0i11Kiw=\n" + - "-----END CERTIFICATE-----"; + "-----BEGIN CERTIFICATE-----\n" + + "MIICkjCCAfugAwIBAgIBADANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" + + "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" + + "MTIwNDE3MTIwNjA3WhcNMzMwMzI4MTIwNjA3WjA7MQswCQYDVQQGEwJVUzENMAsG\n" + + "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwgZ8wDQYJ\n" + + "KoZIhvcNAQEBBQADgY0AMIGJAoGBANY+7Enp+1S566kLcKk+qe4Ki6BxaHGZ+v7r\n" + + "vLksx9IQZCbAEf4YLbrZhKzKD3SPIJXyxPFwknAknIh3Knk8mViOZks7T8L3GnJr\n" + + "TBaVvDyTzDJum/QYiahfO2qpfN/Oya2UILmqsBAeLyWpzbQsAyWBXfoUtkOUgnzK\n" + + "fk6QAKYrAgMBAAGjgaUwgaIwHQYDVR0OBBYEFEtmQi7jT1ijXOafPsfkrLwSVu9e\n" + + "MGMGA1UdIwRcMFqAFEtmQi7jT1ijXOafPsfkrLwSVu9eoT+kPTA7MQswCQYDVQQG\n" + + "EwJVUzENMAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2\n" + + "Y2WCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAQYwDQYJKoZIhvcNAQEE\n" + + "BQADgYEAkKWxMc4+ODk5WwLXXweB8/IKfVfrizNn0KLEgsZ6xNXFIXDpiPGAFcgl\n" + + "MzFO424JgyvUulsUc/X16Cnuwwntkk6KUG7vEV7h4o9sAV7Cax3gfQE/EZFb4ybn\n" + + "aBm1UsujMKd/ovqbbbxJbmOWzCeo0QfIGleDEyh3NBBZ0i11Kiw=\n" + + "-----END CERTIFICATE-----"; // web server certificate, www.example.com static String targetCertStr_A = - "-----BEGIN CERTIFICATE-----\n" + - "MIICVTCCAb6gAwIBAgIBAjANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" + - "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" + - "MTIwNDE3MTIwNjA4WhcNMzIwMTAzMTIwNjA4WjBVMQswCQYDVQQGEwJVUzENMAsG\n" + - "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxGDAWBgNV\n" + - "BAMTD3d3dy5leGFtcGxlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA\n" + - "4zFp3PZNzsd3ZwG6FNNWO9eSN+UBymlf8oCwpKJM2tIinmMWvWIXnlx/2UXIfSAq\n" + - "QEG3aXkAFyEiGGpQlBbqcfrESsHsiz2pnnm5dG2v/eS0Bwz1jmcuNmwnh3UQw2Vl\n" + - "+BLk8ukdrLjiCT8jARiHExYf1Xg+wUqQ9y8NV26hdaUCAwEAAaNPME0wCwYDVR0P\n" + - "BAQDAgPoMB0GA1UdDgQWBBQwtx+gqzn2w4y82brXlp7tqBYEZDAfBgNVHSMEGDAW\n" + - "gBRLZkIu409Yo1zmnz7H5Ky8ElbvXjANBgkqhkiG9w0BAQQFAAOBgQAJWo8B6Ud+\n" + - "/OU+UcZLihlfMX02OSlK2ZB7mfqpj2G3JT9yb0A+VbY3uuajmaYYIIxl3kXGz/n8\n" + - "M2Q/Ux/MDxG+IFKHC26Kuj4dAQgzjq2pILVPTE2QnaQTNCsgVZtTaC47SG9FRSoC\n" + - "qvnIvn/oTpKSqus76I1cR4joDtiV2OEuVw==\n" + - "-----END CERTIFICATE-----"; + "-----BEGIN CERTIFICATE-----\n" + + "MIICVTCCAb6gAwIBAgIBAjANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" + + "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" + + "MTIwNDE3MTIwNjA4WhcNMzIwMTAzMTIwNjA4WjBVMQswCQYDVQQGEwJVUzENMAsG\n" + + "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxGDAWBgNV\n" + + "BAMTD3d3dy5leGFtcGxlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA\n" + + "4zFp3PZNzsd3ZwG6FNNWO9eSN+UBymlf8oCwpKJM2tIinmMWvWIXnlx/2UXIfSAq\n" + + "QEG3aXkAFyEiGGpQlBbqcfrESsHsiz2pnnm5dG2v/eS0Bwz1jmcuNmwnh3UQw2Vl\n" + + "+BLk8ukdrLjiCT8jARiHExYf1Xg+wUqQ9y8NV26hdaUCAwEAAaNPME0wCwYDVR0P\n" + + "BAQDAgPoMB0GA1UdDgQWBBQwtx+gqzn2w4y82brXlp7tqBYEZDAfBgNVHSMEGDAW\n" + + "gBRLZkIu409Yo1zmnz7H5Ky8ElbvXjANBgkqhkiG9w0BAQQFAAOBgQAJWo8B6Ud+\n" + + "/OU+UcZLihlfMX02OSlK2ZB7mfqpj2G3JT9yb0A+VbY3uuajmaYYIIxl3kXGz/n8\n" + + "M2Q/Ux/MDxG+IFKHC26Kuj4dAQgzjq2pILVPTE2QnaQTNCsgVZtTaC47SG9FRSoC\n" + + "qvnIvn/oTpKSqus76I1cR4joDtiV2OEuVw==\n" + + "-----END CERTIFICATE-----"; // Private key in the format of PKCS#8 static String targetPrivateKey_A = - "-----BEGIN PRIVATE KEY-----\n" + - "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAOMxadz2Tc7Hd2cB\n" + - "uhTTVjvXkjflAcppX/KAsKSiTNrSIp5jFr1iF55cf9lFyH0gKkBBt2l5ABchIhhq\n" + - "UJQW6nH6xErB7Is9qZ55uXRtr/3ktAcM9Y5nLjZsJ4d1EMNlZfgS5PLpHay44gk/\n" + - "IwEYhxMWH9V4PsFKkPcvDVduoXWlAgMBAAECgYAqX2nuIyXp3fvgA0twXOYlbRRB\n" + - "Rn3qAXM6qFPJsNeCrFR2k+aG1cev6nKR1FkLNTeMGnWZv06MAcr5IML8i7WXyG4C\n" + - "LY/C0gedn94FDKFlln+bTENwQTGjn4lKysDA+IuNpasTeMCajbic+dPByhIdTOjZ\n" + - "iMCyxbLfpk40zQopVQJBAPyfGmkeHB3GjdbdgujWCGKb2UxBa4O8dy3O4l2yizTn\n" + - "uUqMGcwGY4ciNSVvZQ7jKo4vDmkSuYib4/woPChaNfMCQQDmO0BQuSWYGNtSwV35\n" + - "lafZfX1dNCLKm1iNA6A12evXgvQiE9WT4mqionig0VZW16HtiY4/BkHOcos/K9Um\n" + - "ARQHAkA8mkaRtSF1my5nv1gqVz5Hua+VdZQ/VDUbDiiL5cszc+ulkJqXsWirAG/T\n" + - "fTe3LJQG7A7+8fkEZrF4yoY0AAA1AkEAotokezULj5N9iAL5SzL9wIzQYV4ggfny\n" + - "YATBjXXxKccakwQ+ndWZIiMUeoS4ssLialhTgucVI0fIkU2a/r/ifwJAc6e+5Pvh\n" + - "MghQj/U788Od/v6rgqz/NGsduZ7uilCMcWiwA73OR2MHMH/OIuoofuEPrfuV9isV\n" + - "xVXhgpKfP/pdOA==\n" + - "-----END PRIVATE KEY-----"; + "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAOMxadz2Tc7Hd2cB\n" + + "uhTTVjvXkjflAcppX/KAsKSiTNrSIp5jFr1iF55cf9lFyH0gKkBBt2l5ABchIhhq\n" + + "UJQW6nH6xErB7Is9qZ55uXRtr/3ktAcM9Y5nLjZsJ4d1EMNlZfgS5PLpHay44gk/\n" + + "IwEYhxMWH9V4PsFKkPcvDVduoXWlAgMBAAECgYAqX2nuIyXp3fvgA0twXOYlbRRB\n" + + "Rn3qAXM6qFPJsNeCrFR2k+aG1cev6nKR1FkLNTeMGnWZv06MAcr5IML8i7WXyG4C\n" + + "LY/C0gedn94FDKFlln+bTENwQTGjn4lKysDA+IuNpasTeMCajbic+dPByhIdTOjZ\n" + + "iMCyxbLfpk40zQopVQJBAPyfGmkeHB3GjdbdgujWCGKb2UxBa4O8dy3O4l2yizTn\n" + + "uUqMGcwGY4ciNSVvZQ7jKo4vDmkSuYib4/woPChaNfMCQQDmO0BQuSWYGNtSwV35\n" + + "lafZfX1dNCLKm1iNA6A12evXgvQiE9WT4mqionig0VZW16HtiY4/BkHOcos/K9Um\n" + + "ARQHAkA8mkaRtSF1my5nv1gqVz5Hua+VdZQ/VDUbDiiL5cszc+ulkJqXsWirAG/T\n" + + "fTe3LJQG7A7+8fkEZrF4yoY0AAA1AkEAotokezULj5N9iAL5SzL9wIzQYV4ggfny\n" + + "YATBjXXxKccakwQ+ndWZIiMUeoS4ssLialhTgucVI0fIkU2a/r/ifwJAc6e+5Pvh\n" + + "MghQj/U788Od/v6rgqz/NGsduZ7uilCMcWiwA73OR2MHMH/OIuoofuEPrfuV9isV\n" + + "xVXhgpKfP/pdOA=="; // web server certificate, www.example.net static String targetCertStr_B = - "-----BEGIN CERTIFICATE-----\n" + - "MIICVTCCAb6gAwIBAgIBBDANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" + - "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" + - "MTIwNDE3MTIwNjA5WhcNMzIwMTAzMTIwNjA5WjBVMQswCQYDVQQGEwJVUzENMAsG\n" + - "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxGDAWBgNV\n" + - "BAMTD3d3dy5leGFtcGxlLm5ldDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA\n" + - "2VlzF1fvWYczDChrUeJiLJ1M/dIShCaOTfYGiXfQGEZCAWTacUclwr+rVMnZ75/c\n" + - "wwg5pNdXRijxMil8DBTS1gFcIFQhosLHvzIAe6ULlg/xB+/L6KBz+NTWfo/2KF6t\n" + - "xatmcToNrCcwi7eUOfbzQje65Tizs56jJYem2m7Rk0ECAwEAAaNPME0wCwYDVR0P\n" + - "BAQDAgPoMB0GA1UdDgQWBBQT/FR0cAWcZQ7h0X79KGki34OSQjAfBgNVHSMEGDAW\n" + - "gBRLZkIu409Yo1zmnz7H5Ky8ElbvXjANBgkqhkiG9w0BAQQFAAOBgQB67cPIT6fz\n" + - "6Ws8fBpYgW2ad4ci66i1WduBD9CpGFE+jRK2feRj6hvYBXocKj0AMWUFIEB2E3hA\n" + - "oIjxcf1GxIpHVl9DjlhxqXbA0Ktl7/NGNRlDSLTizOTl3FB1mMTlOGvXDVmpcFhl\n" + - "HuoP1hYvhTsBwPx5igGNchuPtDIUzL2mXw==\n" + - "-----END CERTIFICATE-----"; + "-----BEGIN CERTIFICATE-----\n" + + "MIICVTCCAb6gAwIBAgIBBDANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" + + "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" + + "MTIwNDE3MTIwNjA5WhcNMzIwMTAzMTIwNjA5WjBVMQswCQYDVQQGEwJVUzENMAsG\n" + + "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxGDAWBgNV\n" + + "BAMTD3d3dy5leGFtcGxlLm5ldDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA\n" + + "2VlzF1fvWYczDChrUeJiLJ1M/dIShCaOTfYGiXfQGEZCAWTacUclwr+rVMnZ75/c\n" + + "wwg5pNdXRijxMil8DBTS1gFcIFQhosLHvzIAe6ULlg/xB+/L6KBz+NTWfo/2KF6t\n" + + "xatmcToNrCcwi7eUOfbzQje65Tizs56jJYem2m7Rk0ECAwEAAaNPME0wCwYDVR0P\n" + + "BAQDAgPoMB0GA1UdDgQWBBQT/FR0cAWcZQ7h0X79KGki34OSQjAfBgNVHSMEGDAW\n" + + "gBRLZkIu409Yo1zmnz7H5Ky8ElbvXjANBgkqhkiG9w0BAQQFAAOBgQB67cPIT6fz\n" + + "6Ws8fBpYgW2ad4ci66i1WduBD9CpGFE+jRK2feRj6hvYBXocKj0AMWUFIEB2E3hA\n" + + "oIjxcf1GxIpHVl9DjlhxqXbA0Ktl7/NGNRlDSLTizOTl3FB1mMTlOGvXDVmpcFhl\n" + + "HuoP1hYvhTsBwPx5igGNchuPtDIUzL2mXw==\n" + + "-----END CERTIFICATE-----"; static String targetPrivateKey_B = - "-----BEGIN PRIVATE KEY-----\n" + - "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBANlZcxdX71mHMwwo\n" + - "a1HiYiydTP3SEoQmjk32Bol30BhGQgFk2nFHJcK/q1TJ2e+f3MMIOaTXV0Yo8TIp\n" + - "fAwU0tYBXCBUIaLCx78yAHulC5YP8Qfvy+igc/jU1n6P9ihercWrZnE6DawnMIu3\n" + - "lDn280I3uuU4s7OeoyWHptpu0ZNBAgMBAAECgYEAl19H26sfhD+32rDPxZCgBShs\n" + - "dZ33zVe45i0Bcn4iTLWpxKTDyf7eGps4rO2DvfKdYqt40ggzvSZIjUH9JcDe8GmG\n" + - "d3m0ILB7pg4jsFlpyeHpTO8grPLxA1G9s3o0DoFpz/rooqgFfe/DrRDmRoOSkgfV\n" + - "/gseIbgJHRO/Ctyvdh0CQQD6uFd0HxhH1jl/JzvPzIH4LSnPcdEh9zsMEb6uzh75\n" + - "9qL+IHD5N2I/pYZTKqDFIwhJf701+LKag55AX/zrDt7rAkEA3e00AbnwanDMa6Wj\n" + - "+gFekUQveSVra38LiihzCkyVvQpFjbiF1rUhSNQ0dpU5/hmrYF0C6H9VXAesfkUY\n" + - "WhpDgwJAYjgZOop77piDycZK7isFt32p5XSHIzFBVocVFlH1XKM8UyXOXDNQL/Le\n" + - "XnJSrSf+NRzvuNcG0PVC56Ey6brXpQJAY4M4vcltt5zq3R5CQBmbGRJ1IyKXX3Vx\n" + - "bDslEqoyvri7ZYgnY5aG3UxiVgYmIf3KrgQnCLAIS6MZQumiuMxsFwJAK5pEG063\n" + - "9ngUof4fDMvZphqZjZR1zMKz/V/9ge0DWBINaqFgsgebNu+MyImsC8C6WKjGmV/2\n" + - "f1MY0D7sC2vU/Q==\n" + - "-----END PRIVATE KEY-----"; + "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBANlZcxdX71mHMwwo\n" + + "a1HiYiydTP3SEoQmjk32Bol30BhGQgFk2nFHJcK/q1TJ2e+f3MMIOaTXV0Yo8TIp\n" + + "fAwU0tYBXCBUIaLCx78yAHulC5YP8Qfvy+igc/jU1n6P9ihercWrZnE6DawnMIu3\n" + + "lDn280I3uuU4s7OeoyWHptpu0ZNBAgMBAAECgYEAl19H26sfhD+32rDPxZCgBShs\n" + + "dZ33zVe45i0Bcn4iTLWpxKTDyf7eGps4rO2DvfKdYqt40ggzvSZIjUH9JcDe8GmG\n" + + "d3m0ILB7pg4jsFlpyeHpTO8grPLxA1G9s3o0DoFpz/rooqgFfe/DrRDmRoOSkgfV\n" + + "/gseIbgJHRO/Ctyvdh0CQQD6uFd0HxhH1jl/JzvPzIH4LSnPcdEh9zsMEb6uzh75\n" + + "9qL+IHD5N2I/pYZTKqDFIwhJf701+LKag55AX/zrDt7rAkEA3e00AbnwanDMa6Wj\n" + + "+gFekUQveSVra38LiihzCkyVvQpFjbiF1rUhSNQ0dpU5/hmrYF0C6H9VXAesfkUY\n" + + "WhpDgwJAYjgZOop77piDycZK7isFt32p5XSHIzFBVocVFlH1XKM8UyXOXDNQL/Le\n" + + "XnJSrSf+NRzvuNcG0PVC56Ey6brXpQJAY4M4vcltt5zq3R5CQBmbGRJ1IyKXX3Vx\n" + + "bDslEqoyvri7ZYgnY5aG3UxiVgYmIf3KrgQnCLAIS6MZQumiuMxsFwJAK5pEG063\n" + + "9ngUof4fDMvZphqZjZR1zMKz/V/9ge0DWBINaqFgsgebNu+MyImsC8C6WKjGmV/2\n" + + "f1MY0D7sC2vU/Q=="; // web server certificate, www.invalid.com static String targetCertStr_C = - "-----BEGIN CERTIFICATE-----\n" + - "MIICVTCCAb6gAwIBAgIBAzANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" + - "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" + - "MTIwNDE3MTIwNjA5WhcNMzIwMTAzMTIwNjA5WjBVMQswCQYDVQQGEwJVUzENMAsG\n" + - "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxGDAWBgNV\n" + - "BAMTD3d3dy5pbnZhbGlkLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA\n" + - "q6MyQwzCr2nJ41l0frmHL0qULSyW51MhevBC+1W28i0LE/efrmpwV3LdnlQEGFak\n" + - "DLDwtnff3iru8dSMcA7KdWVkivsE7ZTP+qFDaWBAy7XXiSsv6yZ2Nh4jJb0YcD28\n" + - "45zk2nAl5Az1/PuoTi1vpQxzFZKuBm1HGgz3MEZvBvMCAwEAAaNPME0wCwYDVR0P\n" + - "BAQDAgPoMB0GA1UdDgQWBBRRMifrND015Nm8N6gV5X7cg1YjjjAfBgNVHSMEGDAW\n" + - "gBRLZkIu409Yo1zmnz7H5Ky8ElbvXjANBgkqhkiG9w0BAQQFAAOBgQBjkUO6Ri/B\n" + - "uDC2gDMIyL5+NTe/1dPPQYM4HhCNa/KQYvU5lzCKO9Vpa+i+nyrUNNXUu8Tkyq4Y\n" + - "A+aGSm6+FT/i9rFwkYUdorBtD3KfQiwTIWrVERXBkWI5iZNaVZhx0TFy4vUpf65d\n" + - "QtwkbHpC66fdKc2EdLXkuY9KkmtZZJJ7YA==\n" + - "-----END CERTIFICATE-----"; + "-----BEGIN CERTIFICATE-----\n" + + "MIICVTCCAb6gAwIBAgIBAzANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" + + "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" + + "MTIwNDE3MTIwNjA5WhcNMzIwMTAzMTIwNjA5WjBVMQswCQYDVQQGEwJVUzENMAsG\n" + + "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxGDAWBgNV\n" + + "BAMTD3d3dy5pbnZhbGlkLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA\n" + + "q6MyQwzCr2nJ41l0frmHL0qULSyW51MhevBC+1W28i0LE/efrmpwV3LdnlQEGFak\n" + + "DLDwtnff3iru8dSMcA7KdWVkivsE7ZTP+qFDaWBAy7XXiSsv6yZ2Nh4jJb0YcD28\n" + + "45zk2nAl5Az1/PuoTi1vpQxzFZKuBm1HGgz3MEZvBvMCAwEAAaNPME0wCwYDVR0P\n" + + "BAQDAgPoMB0GA1UdDgQWBBRRMifrND015Nm8N6gV5X7cg1YjjjAfBgNVHSMEGDAW\n" + + "gBRLZkIu409Yo1zmnz7H5Ky8ElbvXjANBgkqhkiG9w0BAQQFAAOBgQBjkUO6Ri/B\n" + + "uDC2gDMIyL5+NTe/1dPPQYM4HhCNa/KQYvU5lzCKO9Vpa+i+nyrUNNXUu8Tkyq4Y\n" + + "A+aGSm6+FT/i9rFwkYUdorBtD3KfQiwTIWrVERXBkWI5iZNaVZhx0TFy4vUpf65d\n" + + "QtwkbHpC66fdKc2EdLXkuY9KkmtZZJJ7YA==\n" + + "-----END CERTIFICATE-----"; static String targetPrivateKey_C = - "-----BEGIN PRIVATE KEY-----\n" + - "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKujMkMMwq9pyeNZ\n" + - "dH65hy9KlC0sludTIXrwQvtVtvItCxP3n65qcFdy3Z5UBBhWpAyw8LZ3394q7vHU\n" + - "jHAOynVlZIr7BO2Uz/qhQ2lgQMu114krL+smdjYeIyW9GHA9vOOc5NpwJeQM9fz7\n" + - "qE4tb6UMcxWSrgZtRxoM9zBGbwbzAgMBAAECgYASJDK40Y12Wvki1Z6xkkyOnBRj\n" + - "XfYpRykfxGtgA2RN3qLwHlk7Zzaul46DIKA6LlYynTUkJDF+Ww1cdDnP0lBlwcmM\n" + - "iD0ck3zYyYBLhQHuVbkK3SYE+ANRhM0icvvqANP2at/U4awQcPNEae/KCiecLNu3\n" + - "CJGqyhPDdrEAqPuJGQJBAN46pQC6l3yrcSYE2s53jSmsm2HVVOFlFXjU6k/RMTxG\n" + - "FfDJtGUAOQ37rPQ06ugr/gjLAmmPp+FXozaBdA32D80CQQDFuGRgv3WYqbglIcRL\n" + - "JRs6xlj9w1F97s/aiUenuwhIPNiUoRbV7mnNuZ/sGF0svOVE7SazRjuFX6UqL9Y9\n" + - "HzG/AkEA170pCI8cl4w8eUNHRB9trGKEKjMXhwVCFh7lJf2ZBcGodSzr8w2HVhrZ\n" + - "Ke7hiemDYffrbJ1oxmv05+o+x3r0lQJBAL6adVm2+FyFMFnLZXmzeb59O4jWY5bt\n" + - "Qz6/HG6bpO5OidMuP99YCHMkQQDOs/PO3Y5GuAoW6IY4n/Y9S2B80+0CQBl1/H9/\n" + - "0n/vrb6vW6Azds49tuS82RFAnOhtwTyBEajs08WF8rZQ3WD2RHJnH0+jjfL0anIp\n" + - "dQBSeNN7s7b6rRk=\n" + - "-----END PRIVATE KEY-----"; + "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAKujMkMMwq9pyeNZ\n" + + "dH65hy9KlC0sludTIXrwQvtVtvItCxP3n65qcFdy3Z5UBBhWpAyw8LZ3394q7vHU\n" + + "jHAOynVlZIr7BO2Uz/qhQ2lgQMu114krL+smdjYeIyW9GHA9vOOc5NpwJeQM9fz7\n" + + "qE4tb6UMcxWSrgZtRxoM9zBGbwbzAgMBAAECgYASJDK40Y12Wvki1Z6xkkyOnBRj\n" + + "XfYpRykfxGtgA2RN3qLwHlk7Zzaul46DIKA6LlYynTUkJDF+Ww1cdDnP0lBlwcmM\n" + + "iD0ck3zYyYBLhQHuVbkK3SYE+ANRhM0icvvqANP2at/U4awQcPNEae/KCiecLNu3\n" + + "CJGqyhPDdrEAqPuJGQJBAN46pQC6l3yrcSYE2s53jSmsm2HVVOFlFXjU6k/RMTxG\n" + + "FfDJtGUAOQ37rPQ06ugr/gjLAmmPp+FXozaBdA32D80CQQDFuGRgv3WYqbglIcRL\n" + + "JRs6xlj9w1F97s/aiUenuwhIPNiUoRbV7mnNuZ/sGF0svOVE7SazRjuFX6UqL9Y9\n" + + "HzG/AkEA170pCI8cl4w8eUNHRB9trGKEKjMXhwVCFh7lJf2ZBcGodSzr8w2HVhrZ\n" + + "Ke7hiemDYffrbJ1oxmv05+o+x3r0lQJBAL6adVm2+FyFMFnLZXmzeb59O4jWY5bt\n" + + "Qz6/HG6bpO5OidMuP99YCHMkQQDOs/PO3Y5GuAoW6IY4n/Y9S2B80+0CQBl1/H9/\n" + + "0n/vrb6vW6Azds49tuS82RFAnOhtwTyBEajs08WF8rZQ3WD2RHJnH0+jjfL0anIp\n" + + "dQBSeNN7s7b6rRk="; // This is a certificate for client - static String targetCertStr_D = - "-----BEGIN CERTIFICATE-----\n" + - "MIICVDCCAb2gAwIBAgIBBTANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" + - "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" + - "MTIwNDE3MTIwNjEwWhcNMzIwMTAzMTIwNjEwWjBUMQswCQYDVQQGEwJVUzENMAsG\n" + - "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxFzAVBgNV\n" + - "BAMTDkludGVyT3AgVGVzdGVyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDo\n" + - "Q/KoAIAC2ljFfW2KwjnxTzi4NQJeUuk2seqKpsAY8x4O5dvixzUl6142zmljapqi\n" + - "bJloQVpfB+CEc5/l4h5gzGRVzkuqP1oPzDrpZ5GsvmvuHenV/TzCIgX1cLETzQVt\n" + - "6Rk06okoBPnw3hDJEJiEc1Rv7HCE8p/p+SaiHrskwwIDAQABo08wTTALBgNVHQ8E\n" + - "BAMCA+gwHQYDVR0OBBYEFPr91O33RIGfFSqza2AwQIgE4QswMB8GA1UdIwQYMBaA\n" + - "FEtmQi7jT1ijXOafPsfkrLwSVu9eMA0GCSqGSIb3DQEBBAUAA4GBANIDFYgAhoj3\n" + - "B8u1YpqeoEp2Lt9TwrYBshaIrbmBPCwCGio0JIsoov3n8BCSg5F+8MnOtPl+TjeO\n" + - "0Ug+7guPdCk/wg8YNxLHgSsQlpcNJDjWiErqmUPVrg5BPPQb65qMund6KTmMN0y6\n" + - "4EbSmxRpZO/N0/5oK4umTk0EeXKNekBj\n" + - "-----END CERTIFICATE-----"; + static String targetCertStr_D= + "-----BEGIN CERTIFICATE-----\n" + + "MIICVDCCAb2gAwIBAgIBBTANBgkqhkiG9w0BAQQFADA7MQswCQYDVQQGEwJVUzEN\n" + + "MAsGA1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UwHhcN\n" + + "MTIwNDE3MTIwNjEwWhcNMzIwMTAzMTIwNjEwWjBUMQswCQYDVQQGEwJVUzENMAsG\n" + + "A1UEChMESmF2YTEdMBsGA1UECxMUU3VuSlNTRSBUZXN0IFNlcml2Y2UxFzAVBgNV\n" + + "BAMTDkludGVyT3AgVGVzdGVyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDo\n" + + "Q/KoAIAC2ljFfW2KwjnxTzi4NQJeUuk2seqKpsAY8x4O5dvixzUl6142zmljapqi\n" + + "bJloQVpfB+CEc5/l4h5gzGRVzkuqP1oPzDrpZ5GsvmvuHenV/TzCIgX1cLETzQVt\n" + + "6Rk06okoBPnw3hDJEJiEc1Rv7HCE8p/p+SaiHrskwwIDAQABo08wTTALBgNVHQ8E\n" + + "BAMCA+gwHQYDVR0OBBYEFPr91O33RIGfFSqza2AwQIgE4QswMB8GA1UdIwQYMBaA\n" + + "FEtmQi7jT1ijXOafPsfkrLwSVu9eMA0GCSqGSIb3DQEBBAUAA4GBANIDFYgAhoj3\n" + + "B8u1YpqeoEp2Lt9TwrYBshaIrbmBPCwCGio0JIsoov3n8BCSg5F+8MnOtPl+TjeO\n" + + "0Ug+7guPdCk/wg8YNxLHgSsQlpcNJDjWiErqmUPVrg5BPPQb65qMund6KTmMN0y6\n" + + "4EbSmxRpZO/N0/5oK4umTk0EeXKNekBj\n" + + "-----END CERTIFICATE-----"; static String targetPrivateKey_D = - "-----BEGIN PRIVATE KEY-----\n" + - "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAOhD8qgAgALaWMV9\n" + - "bYrCOfFPOLg1Al5S6Tax6oqmwBjzHg7l2+LHNSXrXjbOaWNqmqJsmWhBWl8H4IRz\n" + - "n+XiHmDMZFXOS6o/Wg/MOulnkay+a+4d6dX9PMIiBfVwsRPNBW3pGTTqiSgE+fDe\n" + - "EMkQmIRzVG/scITyn+n5JqIeuyTDAgMBAAECgYBw37yIKp4LRONJLnhSq6sO+0n8\n" + - "Mz6waiiN/Q6XTQwj09pysQAYCGlqwSRrDAqpVsBJWO+Ae+oYLrLMi4hUZnwN75v3\n" + - "pe1nXlrD11RmPLXwBxqFxNSvAs2FgLHZEtwHI7Bn8KybT/8bGkQ8csLceInYtMDD\n" + - "MuTyy2KRk/pj60zIKQJBAPgebQiAH6viFQ88AwHaNvQhlUfwmSC1i6f8LVoeqaHC\n" + - "lnP0LJBwlyDeeEInhHrCR2ibnCB6I/Pig+49XQgabK8CQQDvpJwuGEbsOO+3rkJJ\n" + - "OpOw4toG0QJZdRnT6l8I6BlboQRZSfFh+lGGahvFXkxc4KdUpJ7QPtXU7HHk6Huk\n" + - "8RYtAkA9CW8VGj+wTuuTVdX/jKjcIa7RhbSFwWNbrcOSWdys+Gt+luCnn6rt4QyA\n" + - "aaxDbquWZkFgE+voQR7nap0KM0XtAkAznd0WAJymHM1lXt9gLoHJQ9N6TGKZKiPa\n" + - "BU1a+cMcfV4WbVrUo7oTnZ9Fr73681iXXq3mZOJh7lvJ1llreZIxAkBEnbiTgEf4\n" + - "tvku68jHcRbRPmdS7CBSWNEBaHLOm4pUSTcxVTKKMHw7vmM5/UYUxJ8QNKCYxn6O\n" + - "+vtiBwBawwzN\n" + - "-----END PRIVATE KEY-----"; + "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAOhD8qgAgALaWMV9\n" + + "bYrCOfFPOLg1Al5S6Tax6oqmwBjzHg7l2+LHNSXrXjbOaWNqmqJsmWhBWl8H4IRz\n" + + "n+XiHmDMZFXOS6o/Wg/MOulnkay+a+4d6dX9PMIiBfVwsRPNBW3pGTTqiSgE+fDe\n" + + "EMkQmIRzVG/scITyn+n5JqIeuyTDAgMBAAECgYBw37yIKp4LRONJLnhSq6sO+0n8\n" + + "Mz6waiiN/Q6XTQwj09pysQAYCGlqwSRrDAqpVsBJWO+Ae+oYLrLMi4hUZnwN75v3\n" + + "pe1nXlrD11RmPLXwBxqFxNSvAs2FgLHZEtwHI7Bn8KybT/8bGkQ8csLceInYtMDD\n" + + "MuTyy2KRk/pj60zIKQJBAPgebQiAH6viFQ88AwHaNvQhlUfwmSC1i6f8LVoeqaHC\n" + + "lnP0LJBwlyDeeEInhHrCR2ibnCB6I/Pig+49XQgabK8CQQDvpJwuGEbsOO+3rkJJ\n" + + "OpOw4toG0QJZdRnT6l8I6BlboQRZSfFh+lGGahvFXkxc4KdUpJ7QPtXU7HHk6Huk\n" + + "8RYtAkA9CW8VGj+wTuuTVdX/jKjcIa7RhbSFwWNbrcOSWdys+Gt+luCnn6rt4QyA\n" + + "aaxDbquWZkFgE+voQR7nap0KM0XtAkAznd0WAJymHM1lXt9gLoHJQ9N6TGKZKiPa\n" + + "BU1a+cMcfV4WbVrUo7oTnZ9Fr73681iXXq3mZOJh7lvJ1llreZIxAkBEnbiTgEf4\n" + + "tvku68jHcRbRPmdS7CBSWNEBaHLOm4pUSTcxVTKKMHw7vmM5/UYUxJ8QNKCYxn6O\n" + + "+vtiBwBawwzN"; static String[] serverCerts = {targetCertStr_A, targetCertStr_B, targetCertStr_C}; @@ -256,7 +235,7 @@ public class SSLSocketSNISensitive { static String[] clientCerts = {targetCertStr_D}; static String[] clientKeys = {targetPrivateKey_D}; - static char[] passphrase = "passphrase".toCharArray(); + static char passphrase[] = "passphrase".toCharArray(); /* * Is the server ready to serve? @@ -266,7 +245,7 @@ public class SSLSocketSNISensitive { /* * Turn on SSL debugging? */ - static boolean debug = Boolean.getBoolean("test.debug"); + static boolean debug = false; /* * Define the server side of the test. @@ -383,16 +362,19 @@ private static void parseArguments(String[] args) { private static SSLContext generateSSLContext(boolean isClient) throws Exception { - final PEMDecoder pemDecoder = PEMDecoder.of(); + // generate certificate from cert string + CertificateFactory cf = CertificateFactory.getInstance("X.509"); // create a key store KeyStore ks = KeyStore.getInstance("JKS"); ks.load(null, null); - // generate certificate from cert string - Certificate trusedCert = pemDecoder.decode(trustedCertStr, X509Certificate.class); - // import the trused cert + ByteArrayInputStream is = + new ByteArrayInputStream(trustedCertStr.getBytes()); + Certificate trusedCert = cf.generateCertificate(is); + is.close(); + ks.setCertificateEntry("RSA Export Signer", trusedCert); String[] certStrs = null; @@ -408,14 +390,17 @@ private static SSLContext generateSSLContext(boolean isClient) for (int i = 0; i < certStrs.length; i++) { // generate the private key. String keySpecStr = keyStrs[i]; - PKCS8EncodedKeySpec priKeySpec = pemDecoder.decode(keySpecStr, PKCS8EncodedKeySpec.class); + PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec( + Base64.getMimeDecoder().decode(keySpecStr)); KeyFactory kf = KeyFactory.getInstance("RSA"); RSAPrivateKey priKey = (RSAPrivateKey)kf.generatePrivate(priKeySpec); // generate certificate chain String keyCertStr = certStrs[i]; - Certificate keyCert = pemDecoder.decode(keyCertStr, X509Certificate.class); + is = new ByteArrayInputStream(keyCertStr.getBytes()); + Certificate keyCert = cf.generateCertificate(is); + is.close(); Certificate[] chain = new Certificate[2]; chain[0] = keyCert; @@ -536,20 +521,22 @@ public static void main(String[] args) throws Exception { void startServer(boolean newThread) throws Exception { if (newThread) { - serverThread = new Thread(() -> { - try { - doServerSide(); - } catch (Exception e) { - /* - * Our server thread just died. - * - * Release the client, if not active already... - */ - System.err.println("Server died, because of " + e); - serverReady = true; - serverException = e; + serverThread = new Thread() { + public void run() { + try { + doServerSide(); + } catch (Exception e) { + /* + * Our server thread just died. + * + * Release the client, if not active already... + */ + System.err.println("Server died, because of " + e); + serverReady = true; + serverException = e; + } } - }); + }; serverThread.start(); } else { try { @@ -564,17 +551,19 @@ void startServer(boolean newThread) throws Exception { void startClient(boolean newThread) throws Exception { if (newThread) { - clientThread = new Thread(() -> { - try { - doClientSide(); - } catch (Exception e) { - /* - * Our client thread just died. - */ - System.err.println("Client died, because of " + e); - clientException = e; + clientThread = new Thread() { + public void run() { + try { + doClientSide(); + } catch (Exception e) { + /* + * Our client thread just died. + */ + System.err.println("Client died, because of " + e); + clientException = e; + } } - }); + }; clientThread.start(); } else { try { diff --git a/test/jdk/javax/net/ssl/interop/ClientHelloBufferUnderflowException.java b/test/jdk/javax/net/ssl/interop/ClientHelloBufferUnderflowException.java index 0b030c7145989..ca5742f37b2cd 100644 --- a/test/jdk/javax/net/ssl/interop/ClientHelloBufferUnderflowException.java +++ b/test/jdk/javax/net/ssl/interop/ClientHelloBufferUnderflowException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -30,7 +30,6 @@ * @test * @bug 8215790 8219389 * @summary Verify exception - * @enablePreview * @library /test/lib * @modules java.base/sun.security.util * @run main/othervm ClientHelloBufferUnderflowException diff --git a/test/jdk/javax/net/ssl/interop/ClientHelloChromeInterOp.java b/test/jdk/javax/net/ssl/interop/ClientHelloChromeInterOp.java index bcdfa27039424..f426cce33e311 100644 --- a/test/jdk/javax/net/ssl/interop/ClientHelloChromeInterOp.java +++ b/test/jdk/javax/net/ssl/interop/ClientHelloChromeInterOp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -30,7 +30,6 @@ * @test * @bug 8169362 * @summary Interop automated testing with Chrome - * @enablePreview * @library /test/lib * @modules jdk.crypto.ec * java.base/sun.security.util diff --git a/test/jdk/javax/net/ssl/interop/ClientHelloInterOp.java b/test/jdk/javax/net/ssl/interop/ClientHelloInterOp.java index 808d137223e96..c6bf74bd53325 100644 --- a/test/jdk/javax/net/ssl/interop/ClientHelloInterOp.java +++ b/test/jdk/javax/net/ssl/interop/ClientHelloInterOp.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,22 +21,17 @@ * questions. */ -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLEngine; -import javax.net.ssl.SSLEngineResult; -import javax.net.ssl.SSLEngineResult.HandshakeStatus; -import javax.net.ssl.SSLSession; -import javax.net.ssl.TrustManagerFactory; -import java.nio.ByteBuffer; +import javax.net.ssl.*; +import javax.net.ssl.SSLEngineResult.*; +import java.io.*; +import java.nio.*; import java.security.KeyStore; -import java.security.PEMDecoder; -import java.security.PEMRecord; import java.security.PrivateKey; +import java.security.KeyFactory; import java.security.cert.Certificate; -import java.security.cert.X509Certificate; -import java.security.interfaces.ECPrivateKey; -import java.security.interfaces.RSAPrivateKey; +import java.security.cert.CertificateFactory; +import java.security.spec.*; +import java.util.Base64; public abstract class ClientHelloInterOp { @@ -143,16 +138,13 @@ public abstract class ClientHelloInterOp { // // EC private key related to cert endEntityCertStrs[0]. // - "-----BEGIN PRIVATE KEY-----\n" + "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgA3pmS+OrIjGyUv2F\n" + "K/PkyayJIePM2RTFYxNoQqmJGnihRANCAASHi9c1QnNQurh7t8A68XRaJZTpyWU4\n" + - "Ay6zUapMW9ydE84KGXyy5my+Sw7QKlmoveGNeZVf12nUVX+tQEYujVob\n" + - "-----END PRIVATE KEY-----", + "Ay6zUapMW9ydE84KGXyy5my+Sw7QKlmoveGNeZVf12nUVX+tQEYujVob", // // RSA private key related to cert endEntityCertStrs[1]. // - "-----BEGIN PRIVATE KEY-----\n" + "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDfq0lpd8nYH8AW\n" + "8RL62e57JA9I0AFW72d8x1T40Q9qYn4UftwQXxnVKmvW+VCA3MKkNRWt+eZPvmsJ\n" + "qmDPmV0D37L7eF19TIeNkHPN/H7oYdcsHi7p5TY0BNru+pIs1twtx9nv9CaQWqDg\n" + @@ -178,9 +170,8 @@ public abstract class ClientHelloInterOp { "sZ2JRtyK3OV9RtL/MYmYzPLqm1Ah02+GXLVNnvKWmwKBgE8Ble8CzrXYuuPdGxXz\n" + "BZU6HnXQrmTUcgeze0tj8SDHzCfsGsaG6pHrVNkT7CKsRuCHTZLM0kXmUijLFKuP\n" + "5xyE257z4IbbEbs+tcbB3p28n4/47MzZkSR3kt8+FrsEMZq5oOHbFTGzgp9dhZCC\n" + - "dKUqlw5BPHdbxoWB/JpSHGCV\n" + - "-----END PRIVATE KEY-----" - }; + "dKUqlw5BPHdbxoWB/JpSHGCV" + }; // Private key names of endEntityPrivateKeys. private final static String[] endEntityPrivateKeyNames = { @@ -188,8 +179,6 @@ public abstract class ClientHelloInterOp { "RSA" }; - private static final PEMDecoder pemDecoder = PEMDecoder.of(); - /* * Run the test case. */ @@ -262,9 +251,13 @@ protected SSLContext createSSLContext( KeyStore ts = null; // trust store KeyStore ks = null; // key store - char[] passphrase = "passphrase".toCharArray(); + char passphrase[] = "passphrase".toCharArray(); + + // Generate certificate from cert string. + CertificateFactory cf = CertificateFactory.getInstance("X.509"); // Import the trused certs. + ByteArrayInputStream is; if (trustedMaterials != null && trustedMaterials.length != 0) { ts = KeyStore.getInstance("JKS"); ts.load(null, null); @@ -273,8 +266,13 @@ protected SSLContext createSSLContext( new Certificate[trustedMaterials.length]; for (int i = 0; i < trustedMaterials.length; i++) { String trustedCertStr = trustedMaterials[i]; - // Generate certificate from cert string. - trustedCert[i] = pemDecoder.decode(trustedCertStr, X509Certificate.class); + + is = new ByteArrayInputStream(trustedCertStr.getBytes()); + try { + trustedCert[i] = cf.generateCertificate(is); + } finally { + is.close(); + } ts.setCertificateEntry("trusted-cert-" + i, trustedCert[i]); } @@ -297,14 +295,21 @@ protected SSLContext createSSLContext( String keyCertStr = keyMaterialCerts[i]; // generate the private key. - PrivateKey priKey = switch (keyMaterialKeyAlgs[i]) { - case "RSA" -> pemDecoder.decode(keyMaterialKeys[i], RSAPrivateKey.class); - case "EC" -> pemDecoder.decode(keyMaterialKeys[i], ECPrivateKey.class); - default -> pemDecoder.decode(keyMaterialKeys[i], PrivateKey.class); - }; + PKCS8EncodedKeySpec priKeySpec = new PKCS8EncodedKeySpec( + Base64.getMimeDecoder().decode(keyMaterialKeys[i])); + KeyFactory kf = + KeyFactory.getInstance(keyMaterialKeyAlgs[i]); + PrivateKey priKey = kf.generatePrivate(priKeySpec); // generate certificate chain - Certificate keyCert = pemDecoder.decode(keyCertStr, X509Certificate.class); + is = new ByteArrayInputStream(keyCertStr.getBytes()); + Certificate keyCert = null; + try { + keyCert = cf.generateCertificate(is); + } finally { + is.close(); + } + Certificate[] chain = new Certificate[] { keyCert }; // import the key entry. diff --git a/test/jdk/javax/swing/JColorChooser/Test4234761.java b/test/jdk/javax/swing/JColorChooser/Test4234761.java index fb55ca37feb7f..c2b2d9ed7b9b2 100644 --- a/test/jdk/javax/swing/JColorChooser/Test4234761.java +++ b/test/jdk/javax/swing/JColorChooser/Test4234761.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,12 +23,10 @@ /* * @test - * @bug 4234761 * @key headful + * @bug 4234761 * @summary RGB values sholdn't be changed in transition to HSB tab - * @library /test/lib - * @build jtreg.SkippedException - * @run main Test4234761 + * @author Oleg Mokhovikov */ import java.awt.Color; @@ -37,17 +35,11 @@ import javax.swing.JColorChooser; import javax.swing.JDialog; import javax.swing.JTabbedPane; -import javax.swing.UIManager; - -import jtreg.SkippedException; public class Test4234761 implements PropertyChangeListener { private static final Color COLOR = new Color(51, 51, 51); public static void main(String[] args) { - if (UIManager.getLookAndFeel().getName().contains("GTK")) { - throw new SkippedException("Test skipped for GTK"); - } JColorChooser chooser = new JColorChooser(COLOR); JDialog dialog = Test4177735.show(chooser); diff --git a/test/jdk/javax/swing/JSlider/bug4382876.java b/test/jdk/javax/swing/JSlider/bug4382876.java index b0988de3cabdf..b9ec64aab216c 100644 --- a/test/jdk/javax/swing/JSlider/bug4382876.java +++ b/test/jdk/javax/swing/JSlider/bug4382876.java @@ -48,8 +48,8 @@ public class bug4382876 { private static Robot r; private static JFrame f; private static JSlider slider; - private static volatile boolean upFail; - private static volatile boolean downFail; + private static boolean upFail; + private static boolean downFail; public static void main(String[] args) throws Exception { try { @@ -70,30 +70,23 @@ public static void main(String[] args) throws Exception { r.delay(1000); r.keyPress(KeyEvent.VK_PAGE_UP); - r.keyRelease(KeyEvent.VK_PAGE_UP); - SwingUtilities.invokeAndWait(() -> { if (slider.getValue() < -1000) { System.out.println("PAGE_UP VAL: " + slider.getValue()); upFail = true; } }); - if (upFail) { writeFailImage(); throw new RuntimeException("Slider value did NOT change with PAGE_UP"); } - r.keyPress(KeyEvent.VK_PAGE_DOWN); - r.keyRelease(KeyEvent.VK_PAGE_DOWN); - SwingUtilities.invokeAndWait(() -> { if (slider.getValue() > -1000) { System.out.println("PAGE_DOWN VAL: " + slider.getValue()); downFail = true; } }); - if (downFail) { writeFailImage(); throw new RuntimeException("Slider value did NOT change with PAGE_DOWN"); diff --git a/test/jdk/javax/swing/JSpinner/8223788/JSpinnerButtonFocusTest.java b/test/jdk/javax/swing/JSpinner/8223788/JSpinnerButtonFocusTest.java index 994a03959b2bd..4060042ca4f7d 100644 --- a/test/jdk/javax/swing/JSpinner/8223788/JSpinnerButtonFocusTest.java +++ b/test/jdk/javax/swing/JSpinner/8223788/JSpinnerButtonFocusTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 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 @@ -63,7 +63,7 @@ public static void main(String args[]) throws Exception { robot.setAutoDelay(50); SwingUtilities.invokeAndWait(() -> { - frame = new JFrame("JSpinnerButtonFocusTest"); + frame = new JFrame(); spinner1 = new JSpinner(); spinner2 = new JSpinner(); @@ -72,15 +72,6 @@ public static void main(String args[]) throws Exception { frame.getContentPane().add(spinner2, BorderLayout.SOUTH); editor1 = ((DefaultEditor)spinner1.getEditor()); - editor1.getTextField().addFocusListener(new FocusAdapter() { - @Override - public void focusGained(FocusEvent e) { - super.focusGained(e); - robot.keyPress(KeyEvent.VK_TAB); - robot.keyRelease(KeyEvent.VK_TAB); - latch1.countDown(); - } - }); editor1.setFocusable(false); spinner1.setFocusable(false); @@ -93,18 +84,26 @@ public void focusGained(FocusEvent e) { frame.setFocusTraversalPolicyProvider(true); frame.setAlwaysOnTop(true); - frame.setSize(100, 100); - frame.setLocationRelativeTo(null); + frame.pack(); frame.setVisible(true); }); robot.waitForIdle(); - robot.delay(1000); + + editor1.getTextField().addFocusListener(new FocusAdapter() { + @Override + public void focusGained(FocusEvent e) { + super.focusGained(e); + robot.keyPress(KeyEvent.VK_TAB); + robot.keyRelease(KeyEvent.VK_TAB); + latch1.countDown(); + } + }); SwingUtilities.invokeAndWait(() -> { editor1.getTextField().requestFocusInWindow(); }); - if (!latch1.await(1, TimeUnit.MINUTES)) { + if (!latch1.await(15, TimeUnit.MINUTES)) { throw new RuntimeException(LF.getClassName() + ": Timeout waiting for editor1 to gain focus."); } diff --git a/test/jdk/javax/swing/JTabbedPane/4624207/bug4624207.java b/test/jdk/javax/swing/JTabbedPane/4624207/bug4624207.java index 4d2fdcf030cd8..10de2ab221ad4 100644 --- a/test/jdk/javax/swing/JTabbedPane/4624207/bug4624207.java +++ b/test/jdk/javax/swing/JTabbedPane/4624207/bug4624207.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,26 +25,25 @@ * @test * @key headful * @bug 4624207 - * @requires (os.family != "mac") * @summary JTabbedPane mnemonics don't work from outside the tabbed pane + * @author Oleg Mokhovikov + * @library /test/lib + * @library ../../regtesthelpers + * @build Util jdk.test.lib.Platform * @run main bug4624207 */ - -import java.awt.BorderLayout; -import java.awt.Robot; +import javax.swing.*; +import javax.swing.event.ChangeEvent; +import javax.swing.event.ChangeListener; +import java.awt.*; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.KeyEvent; -import javax.swing.JButton; -import javax.swing.JFrame; -import javax.swing.JTabbedPane; -import javax.swing.JTextField; -import javax.swing.SwingUtilities; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; +import jdk.test.lib.Platform; public class bug4624207 implements ChangeListener, FocusListener { + private static volatile boolean stateChanged = false; private static volatile boolean focusGained = false; private static JTextField txtField; @@ -72,39 +71,51 @@ public static void main(String[] args) throws Exception { Robot robot = new Robot(); robot.setAutoDelay(50); - SwingUtilities.invokeAndWait(() -> createAndShowGUI()); + SwingUtilities.invokeAndWait(new Runnable() { + + public void run() { + createAndShowGUI(); + } + }); + robot.waitForIdle(); - SwingUtilities.invokeAndWait(() -> txtField.requestFocus()); + + SwingUtilities.invokeAndWait(new Runnable() { + + public void run() { + txtField.requestFocus(); + } + }); + robot.waitForIdle(); if (!focusGained) { throw new RuntimeException("Couldn't gain focus for text field"); } - SwingUtilities.invokeAndWait(() -> { - tab.addChangeListener((ChangeListener) listener); - txtField.removeFocusListener((FocusListener) listener); + SwingUtilities.invokeAndWait(new Runnable() { + + public void run() { + tab.addChangeListener((ChangeListener) listener); + txtField.removeFocusListener((FocusListener) listener); + } }); robot.waitForIdle(); - robot.keyPress(KeyEvent.VK_ALT); - robot.keyPress(KeyEvent.VK_B); - robot.keyRelease(KeyEvent.VK_B); - robot.keyRelease(KeyEvent.VK_ALT); + if (Platform.isOSX()) { + Util.hitKeys(robot, KeyEvent.VK_CONTROL, KeyEvent.VK_ALT, KeyEvent.VK_B); + } else { + Util.hitKeys(robot, KeyEvent.VK_ALT, KeyEvent.VK_B); + } robot.waitForIdle(); if (!stateChanged || tab.getSelectedIndex() != 1) { - throw new RuntimeException("JTabbedPane mnemonics don't " + - "work from outside the tabbed pane"); + throw new RuntimeException("JTabbedPane mnemonics don't work from outside the tabbed pane"); } } finally { - SwingUtilities.invokeAndWait(() -> { - if (frame != null) { - frame.dispose(); - } - }); + if (frame != null) SwingUtilities.invokeAndWait(() -> frame.dispose()); } } diff --git a/test/jdk/javax/swing/plaf/motif/bug4150591.java b/test/jdk/javax/swing/plaf/motif/bug4150591.java index f3614908cfff4..66c668a441c38 100644 --- a/test/jdk/javax/swing/plaf/motif/bug4150591.java +++ b/test/jdk/javax/swing/plaf/motif/bug4150591.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,6 @@ import com.sun.java.swing.plaf.motif.MotifInternalFrameTitlePane; import javax.swing.JInternalFrame; -import javax.swing.UIManager; /* * @test @@ -37,8 +36,7 @@ */ public class bug4150591 { - public static void main(String[] args) throws Exception { - UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel"); + public static void main(String[] args) { MotifInternalFrameTitlePane mtp = new MotifInternalFrameTitlePane(new JInternalFrame()); } } diff --git a/test/jdk/jdk/internal/misc/TerminatingThreadLocal/TestTerminatingThreadLocal.java b/test/jdk/jdk/internal/misc/TerminatingThreadLocal/TestTerminatingThreadLocal.java index bbf2e99b95094..cf46c5b1d224c 100644 --- a/test/jdk/jdk/internal/misc/TerminatingThreadLocal/TestTerminatingThreadLocal.java +++ b/test/jdk/jdk/internal/misc/TerminatingThreadLocal/TestTerminatingThreadLocal.java @@ -23,7 +23,9 @@ import jdk.internal.misc.TerminatingThreadLocal; +import java.lang.reflect.Constructor; import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; import java.util.Arrays; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; @@ -35,8 +37,6 @@ import java.util.function.Function; import java.util.stream.Stream; -import jdk.test.lib.thread.VThreadScheduler; - import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import static org.testng.Assert.*; @@ -46,7 +46,6 @@ * @bug 8202788 8291897 8357637 * @summary TerminatingThreadLocal unit test * @modules java.base/java.lang:+open java.base/jdk.internal.misc - * @library /test/lib * @requires vm.continuations * @run testng/othervm TestTerminatingThreadLocal */ @@ -140,7 +139,7 @@ protected T initialValue() { // capture carrier Thread carrier = pool.submit(Thread::currentThread).get(); - ThreadFactory factory = VThreadScheduler.virtualThreadBuilder(pool) + ThreadFactory factory = virtualThreadBuilder(pool) .name("ttl-test-virtual-", 0) .factory(); try (var executor = Executors.newThreadPerTaskExecutor(factory)) { @@ -203,4 +202,24 @@ protected void threadTerminated(String value) { assertEquals(terminatedValues, List.of(ttlValue)); } + + /** + * Returns a builder to create virtual threads that use the given scheduler. + */ + static Thread.Builder.OfVirtual virtualThreadBuilder(Executor scheduler) { + try { + Class clazz = Class.forName("java.lang.ThreadBuilders$VirtualThreadBuilder"); + Constructor ctor = clazz.getDeclaredConstructor(Executor.class); + ctor.setAccessible(true); + return (Thread.Builder.OfVirtual) ctor.newInstance(scheduler); + } catch (InvocationTargetException e) { + Throwable cause = e.getCause(); + if (cause instanceof RuntimeException re) { + throw re; + } + throw new RuntimeException(e); + } catch (Exception e) { + throw new RuntimeException(e); + } + } } diff --git a/test/jdk/jdk/internal/platform/docker/MetricsMemoryTester.java b/test/jdk/jdk/internal/platform/docker/MetricsMemoryTester.java index c27a1c7480fb4..8069965e8d87d 100644 --- a/test/jdk/jdk/internal/platform/docker/MetricsMemoryTester.java +++ b/test/jdk/jdk/internal/platform/docker/MetricsMemoryTester.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -70,7 +70,7 @@ private static void testMemoryFailCount() { // We need swap to execute this test or will SEGV if (memAndSwapLimit <= memLimit) { - System.out.println("No swap memory limits. Ignoring test!"); + System.out.println("No swap memory limits, test case skipped"); } else { long count = Metrics.systemMetrics().getMemoryFailCount(); diff --git a/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetrics.java b/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetrics.java index 2afb5ed93b1e5..7cbab5c3b868b 100644 --- a/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetrics.java +++ b/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetrics.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,6 @@ import jdk.test.lib.containers.docker.DockerRunOptions; import jdk.test.lib.containers.docker.DockerTestUtils; import jdk.test.lib.process.OutputAnalyzer; -import jtreg.SkippedException; /* * @test @@ -113,22 +112,18 @@ private static void testMemoryFailCount(String value) throws Exception { // Check whether swapping really works for this test // On some systems there is no swap space enabled. And running - // 'java -Xms{mem-limit} -Xmx{mem-limit} -XX:+AlwaysPreTouch -version' - // would fail due to swap space size being 0. Note that when swap is - // properly enabled on the system the container gets the same amount - // of swap as is configured for memory. Thus, 2x{mem-limit} is the actual - // memory and swap bound for this pre-test. + // 'java -Xms{mem-limit} -Xmx{mem-limit} -version' would fail due to swap space size being 0. DockerRunOptions preOpts = new DockerRunOptions(imageName, "/jdk/bin/java", "-version"); preOpts.addDockerOpts("--volume", Utils.TEST_CLASSES + ":/test-classes/") .addDockerOpts("--memory=" + value) - .addJavaOpts("-XX:+AlwaysPreTouch") .addJavaOpts("-Xms" + value) .addJavaOpts("-Xmx" + value); OutputAnalyzer oa = DockerTestUtils.dockerRunJava(preOpts); String output = oa.getOutput(); if (!output.contains("version")) { - throw new SkippedException("Swapping doesn't work for this test."); + System.out.println("Swapping doesn't work for this test."); + return; } DockerRunOptions opts = @@ -142,7 +137,8 @@ private static void testMemoryFailCount(String value) throws Exception { oa = DockerTestUtils.dockerRunJava(opts); output = oa.getOutput(); if (output.contains("Ignoring test")) { - throw new SkippedException("Ignored by the tester"); + System.out.println("Ignored by the tester"); + return; } oa.shouldHaveExitValue(0).shouldContain("TEST PASSED!!!"); } diff --git a/test/jdk/jdk/internal/vm/Continuation/Scoped.java b/test/jdk/jdk/internal/vm/Continuation/Scoped.java index 448c2ab71a5b6..908267792b874 100644 --- a/test/jdk/jdk/internal/vm/Continuation/Scoped.java +++ b/test/jdk/jdk/internal/vm/Continuation/Scoped.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @summary Nested continuations test * @requires vm.continuations - * @requires test.thread.factory == null * @modules java.base/jdk.internal.vm * @build java.base/java.lang.StackWalkerHelper * @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:+ShowHiddenFrames -Xint Scoped diff --git a/test/jdk/sun/java2d/marlin/Bug8341381.java b/test/jdk/sun/java2d/marlin/Bug8341381.java deleted file mode 100644 index b469ac49313e0..0000000000000 --- a/test/jdk/sun/java2d/marlin/Bug8341381.java +++ /dev/null @@ -1,601 +0,0 @@ -/* - * 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. - */ - -import java.awt.BasicStroke; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.Graphics; -import java.awt.Graphics2D; -import java.awt.RenderingHints; -import java.awt.Stroke; -import java.awt.geom.AffineTransform; -import java.awt.geom.CubicCurve2D; -import java.awt.geom.Point2D; -import java.awt.geom.Rectangle2D; -import java.awt.image.BufferedImage; -import java.awt.image.Raster; -import java.io.File; -import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Locale; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.logging.Handler; -import java.util.logging.LogRecord; -import java.util.logging.Logger; - -import javax.imageio.ImageIO; -import javax.swing.JFrame; -import javax.swing.JPanel; -import javax.swing.SwingUtilities; -import javax.swing.Timer; - -import static java.lang.System.out; - -/** - * @test - * @bug 8341381 - * @summary fix cubic offsetting issue (numerical accuracy) - * @run main/othervm/timeout=20 Bug8341381 - * @modules java.desktop/sun.java2d.marlin - */ -public final class Bug8341381 { - - static final boolean SHOW_GUI = false; - - static final boolean CHECK_PIXELS = true; - static final boolean TRACE_ALL = false; - static final boolean TRACE_CHECK_PIXELS = false; - - static final boolean SAVE_IMAGE = false; - - static final boolean INTENSIVE = false; - - static final double DPI = 96; - static final float STROKE_WIDTH = 15f; - - // delay is 1 frame at 60hz - static final int DELAY = 16; - // off-screen test step (1.0 by default) - static final double STEP = (INTENSIVE) ? 1.0 / 117 : 1.0; - - // stats: - static int N_TEST = 0; - static int N_FAIL = 0; - - static final AtomicBoolean isMarlin = new AtomicBoolean(); - static final CountDownLatch latch = new CountDownLatch(1); - - public static void main(final String[] args) { - Locale.setDefault(Locale.US); - - // FIRST: Get Marlin runtime state from its log: - - // initialize j.u.l Logger: - final Logger log = Logger.getLogger("sun.java2d.marlin"); - log.addHandler(new Handler() { - @Override - public void publish(LogRecord record) { - final String msg = record.getMessage(); - if (msg != null) { - // last space to avoid matching other settings: - if (msg.startsWith("sun.java2d.renderer ")) { - isMarlin.set(msg.contains("DMarlinRenderingEngine")); - } - } - - final Throwable th = record.getThrown(); - // detect any Throwable: - if (th != null) { - out.println("Test failed:\n" + record.getMessage()); - th.printStackTrace(out); - throw new RuntimeException("Test failed: ", th); - } - } - - @Override - public void flush() { - } - - @Override - public void close() throws SecurityException { - } - }); - - out.println("Bug8341381: start"); - final long startTime = System.currentTimeMillis(); - - // enable Marlin logging & internal checks: - System.setProperty("sun.java2d.renderer.log", "true"); - System.setProperty("sun.java2d.renderer.useLogger", "true"); - - try { - startTest(); - - out.println("WAITING ..."); - latch.await(15, TimeUnit.SECONDS); // 2s typically - - if (isMarlin.get()) { - out.println("Marlin renderer used at runtime."); - } else { - throw new RuntimeException("Marlin renderer NOT used at runtime !"); - } - - // show test report: - out.println("TESTS: " + N_TEST + " FAILS: " + N_FAIL); - - if (N_FAIL > 0) { - throw new RuntimeException("Bug8341381: " + N_FAIL + " / " + N_TEST + " test(s) failed !"); - } - - } catch (InterruptedException ie) { - throw new RuntimeException(ie); - } catch (InvocationTargetException ite) { - throw new RuntimeException(ite); - } finally { - final double elapsed = (System.currentTimeMillis() - startTime) / 1000.0; - out.println("Bug8341381: end (" + elapsed + " s)"); - } - } - - private static void startTest() throws InterruptedException, InvocationTargetException { - if (SHOW_GUI) { - SwingUtilities.invokeAndWait(new Runnable() { - @Override - public void run() { - final JFrame viewer = new JFrame(); - viewer.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - viewer.setContentPane(new CanvasPanel(viewer)); - viewer.pack(); - viewer.setVisible(true); - } - }); - return; - } else { - out.println("STEP: " + STEP); - new Thread(new Runnable() { - @Override - public void run() { - final Context ctx = new Context(); - final Dimension initialDim = ctx.bugDisplay.getSize(DPI); - - double w = initialDim.width; - double h = initialDim.height; - do { - ctx.shouldScale(w, h); - ctx.paintImage(); - - // resize component: - w -= STEP; - h -= STEP; - - } while (ctx.iterate()); - } - }).start(); - } - } - - static final class Context { - - final BugDisplay bugDisplay = new BugDisplay(); - double width = 0.0, height = 0.0; - - BufferedImage bimg = null; - - boolean shouldScale(final double w, final double h) { - if ((w != width) || (h != height) || !bugDisplay.isScaled) { - width = w; - height = h; - bugDisplay.scale(width, height); - N_TEST++; - return true; - } - return false; - } - - void paintImage() { - final int w = bugDisplay.canvasWidth; - final int h = bugDisplay.canvasHeight; - - if ((bimg == null) || (w > bimg.getWidth()) || (h > bimg.getHeight())) { - bimg = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE); - } - final Graphics gi = bimg.getGraphics(); - try { - bugDisplay.paint(gi); - } finally { - gi.dispose(); - } - if (!bugDisplay.checkImage(bimg)) { - N_FAIL++; - } - } - - boolean iterate() { - if ((bugDisplay.canvasWidth > 10) || (bugDisplay.canvasHeight > 10)) { - // continue: - return true; - } - out.println("Stop"); - latch.countDown(); - return false; - } - } - - static final class CanvasPanel extends JPanel { - private static final long serialVersionUID = 1L; - - private final Context ctx = new Context(); - private boolean resized = false; - private Timer timer = null; - - public CanvasPanel(final JFrame frame) { - timer = new Timer(DELAY, e -> { - if (resized) { - resized = false; - - if (ctx.iterate()) { - // resize component: - setSize((int) Math.round(ctx.width - 1), (int) Math.round(ctx.height - 1)); - } else { - timer.stop(); - if (frame != null) { - frame.setVisible(false); - } - } - } - }); - timer.setCoalesce(true); - timer.setRepeats(true); - timer.start(); - } - - @Override - public void paint(final Graphics g) { - final Dimension dim = getSize(); - if (ctx.shouldScale(dim.width, dim.height)) { - this.resized = true; - } - super.paint(g); - - // paint on buffered image: - if (CHECK_PIXELS) { - final int w = ctx.bugDisplay.canvasWidth; - final int h = ctx.bugDisplay.canvasHeight; - if (this.resized) { - ctx.paintImage(); - } - g.drawImage(ctx.bimg.getSubimage(0, 0, w, h), 0, 0, null); - } else { - ctx.bugDisplay.paint(g); - } - } - - @Override - public Dimension getPreferredSize() { - return ctx.bugDisplay.getSize(DPI); - } - } - - static final class BugDisplay { - - boolean isScaled = false; - int canvasWidth; - int canvasHeight; - - private final static java.util.List curves1 = Arrays.asList( - new CubicCurve2D.Double(2191.0, 7621.0, 2191.0, 7619.0, 2191.0, 7618.0, 2191.0, 7617.0), - new CubicCurve2D.Double(2191.0, 7617.0, 2191.0, 7617.0, 2191.0, 7616.0, 2191.0, 7615.0), - new CubicCurve2D.Double(2198.0, 7602.0, 2200.0, 7599.0, 2203.0, 7595.0, 2205.0, 7590.0), - new CubicCurve2D.Double(2205.0, 7590.0, 2212.0, 7580.0, 2220.0, 7571.0, 2228.0, 7563.0), - new CubicCurve2D.Double(2228.0, 7563.0, 2233.0, 7557.0, 2239.0, 7551.0, 2245.0, 7546.0), - new CubicCurve2D.Double(2245.0, 7546.0, 2252.0, 7540.0, 2260.0, 7534.0, 2267.0, 7528.0), - new CubicCurve2D.Double(2267.0, 7528.0, 2271.0, 7526.0, 2275.0, 7524.0, 2279.0, 7521.0), - new CubicCurve2D.Double(2279.0, 7521.0, 2279.0, 7520.0, 2280.0, 7520.0, 2281.0, 7519.0) - ); - private final static java.util.List curves2 = Arrays.asList( - new CubicCurve2D.Double(2281.0, 7519.0, 2282.0, 7518.0, 2282.0, 7517.0, 2283.0, 7516.0), - new CubicCurve2D.Double(2283.0, 7516.0, 2284.0, 7515.0, 2284.0, 7515.0, 2285.0, 7514.0), - new CubicCurve2D.Double(2291.0, 7496.0, 2292.0, 7495.0, 2292.0, 7494.0, 2291.0, 7493.0), - new CubicCurve2D.Double(2291.0, 7493.0, 2290.0, 7492.0, 2290.0, 7492.0, 2289.0, 7492.0), - new CubicCurve2D.Double(2289.0, 7492.0, 2288.0, 7491.0, 2286.0, 7492.0, 2285.0, 7492.0), - new CubicCurve2D.Double(2262.0, 7496.0, 2260.0, 7497.0, 2259.0, 7497.0, 2257.0, 7498.0), - new CubicCurve2D.Double(2257.0, 7498.0, 2254.0, 7498.0, 2251.0, 7499.0, 2248.0, 7501.0), - new CubicCurve2D.Double(2248.0, 7501.0, 2247.0, 7501.0, 2245.0, 7502.0, 2244.0, 7503.0), - new CubicCurve2D.Double(2207.0, 7523.0, 2203.0, 7525.0, 2199.0, 7528.0, 2195.0, 7530.0), - new CubicCurve2D.Double(2195.0, 7530.0, 2191.0, 7534.0, 2186.0, 7538.0, 2182.0, 7541.0) - ); - private final static java.util.List curves3 = Arrays.asList( - new CubicCurve2D.Double(2182.0, 7541.0, 2178.0, 7544.0, 2174.0, 7547.0, 2170.0, 7551.0), - new CubicCurve2D.Double(2170.0, 7551.0, 2164.0, 7556.0, 2158.0, 7563.0, 2152.0, 7569.0), - new CubicCurve2D.Double(2152.0, 7569.0, 2148.0, 7573.0, 2145.0, 7577.0, 2141.0, 7582.0), - new CubicCurve2D.Double(2141.0, 7582.0, 2138.0, 7588.0, 2134.0, 7595.0, 2132.0, 7602.0), - new CubicCurve2D.Double(2132.0, 7602.0, 2132.0, 7605.0, 2131.0, 7608.0, 2131.0, 7617.0), - new CubicCurve2D.Double(2131.0, 7617.0, 2131.0, 7620.0, 2131.0, 7622.0, 2131.0, 7624.0), - new CubicCurve2D.Double(2131.0, 7624.0, 2131.0, 7630.0, 2132.0, 7636.0, 2135.0, 7641.0), - new CubicCurve2D.Double(2135.0, 7641.0, 2136.0, 7644.0, 2137.0, 7647.0, 2139.0, 7650.0), - new CubicCurve2D.Double(2139.0, 7650.0, 2143.0, 7658.0, 2149.0, 7664.0, 2155.0, 7670.0), - new CubicCurve2D.Double(2155.0, 7670.0, 2160.0, 7676.0, 2165.0, 7681.0, 2171.0, 7686.0) - ); - private final static java.util.List curves4 = Arrays.asList( - new CubicCurve2D.Double(2171.0, 7686.0, 2174.0, 7689.0, 2177.0, 7692.0, 2180.0, 7694.0), - new CubicCurve2D.Double(2180.0, 7694.0, 2185.0, 7698.0, 2191.0, 7702.0, 2196.0, 7706.0), - new CubicCurve2D.Double(2196.0, 7706.0, 2199.0, 7708.0, 2203.0, 7711.0, 2207.0, 7713.0), - new CubicCurve2D.Double(2244.0, 7734.0, 2245.0, 7734.0, 2247.0, 7735.0, 2248.0, 7736.0), - new CubicCurve2D.Double(2248.0, 7736.0, 2251.0, 7738.0, 2254.0, 7739.0, 2257.0, 7739.0), - new CubicCurve2D.Double(2257.0, 7739.0, 2259.0, 7739.0, 2260.0, 7739.0, 2262.0, 7740.0), - new CubicCurve2D.Double(2285.0, 7745.0, 2286.0, 7745.0, 2288.0, 7745.0, 2289.0, 7745.0), - new CubicCurve2D.Double(2289.0, 7745.0, 2290.0, 7745.0, 2290.0, 7744.0, 2291.0, 7743.0), - new CubicCurve2D.Double(2291.0, 7743.0, 2292.0, 7742.0, 2292.0, 7741.0, 2291.0, 7740.0), - new CubicCurve2D.Double(2285.0, 7722.0, 2284.0, 7721.0, 2284.0, 7721.0, 2283.0, 7720.0), - new CubicCurve2D.Double(2283.0, 7720.0, 2282.0, 7719.0, 2282.0, 7719.0, 2281.0, 7718.0), - new CubicCurve2D.Double(2281.0, 7718.0, 2280.0, 7717.0, 2279.0, 7716.0, 2279.0, 7716.0), - new CubicCurve2D.Double(2279.0, 7716.0, 2275.0, 7712.0, 2271.0, 7710.0, 2267.0, 7708.0), - new CubicCurve2D.Double(2267.0, 7708.0, 2260.0, 7702.0, 2252.0, 7697.0, 2245.0, 7691.0), - new CubicCurve2D.Double(2245.0, 7691.0, 2239.0, 7685.0, 2233.0, 7679.0, 2228.0, 7673.0), - new CubicCurve2D.Double(2228.0, 7673.0, 2220.0, 7665.0, 2212.0, 7656.0, 2205.0, 7646.0), - new CubicCurve2D.Double(2205.0, 7646.0, 2203.0, 7641.0, 2200.0, 7637.0, 2198.0, 7634.0) - ); - - private final static Point2D.Double[] extent = {new Point2D.Double(0.0, 0.0), new Point2D.Double(7777.0, 10005.0)}; - - private final static Stroke STROKE = new BasicStroke(STROKE_WIDTH); - private final static Stroke STROKE_DASHED = new BasicStroke(STROKE_WIDTH, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, - 10.0f, new float[] {100f, 0f}, 0.0f); - - // members: - private final java.util.List allCurves = new ArrayList<>(); - private final Rectangle2D bboxAllCurves = new Rectangle2D.Double(); - - BugDisplay() { - allCurves.addAll(curves1); - allCurves.addAll(curves2); - allCurves.addAll(curves3); - allCurves.addAll(curves4); - - // initialize bounding box: - double x1 = Double.POSITIVE_INFINITY; - double y1 = Double.POSITIVE_INFINITY; - double x2 = Double.NEGATIVE_INFINITY; - double y2 = Double.NEGATIVE_INFINITY; - - for (final CubicCurve2D c : allCurves) { - final Rectangle2D r = c.getBounds2D(); - if (r.getMinX() < x1) { - x1 = r.getMinX(); - } - if (r.getMinY() < y1) { - y1 = r.getMinY(); - } - if (r.getMaxX() > x2) { - x2 = r.getMaxX(); - } - if (r.getMaxY() > y2) { - y2 = r.getMaxY(); - } - } - // add margin of 10%: - final double m = 1.1 * STROKE_WIDTH; - bboxAllCurves.setFrameFromDiagonal(x1 - m, y1 - m, x2 + m, y2 + m); - } - - public void paint(final Graphics g) { - final Graphics2D g2d = (Graphics2D) g; - g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); - g2d.setColor(Color.WHITE); - g2d.fillRect(0, 0, this.canvasWidth, this.canvasHeight); - - // ------ scale - final AffineTransform tx_orig = g2d.getTransform(); - final AffineTransform tx = getDrawTransform(); - g2d.transform(tx); - - // draw bbox: - if (!CHECK_PIXELS) { - g2d.setColor(Color.RED); - g2d.setStroke(STROKE); - g2d.draw(bboxAllCurves); - } - // draw curves: - g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); - g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE); - g2d.setColor(Color.BLACK); - - // dasher + stroker: - g2d.setStroke(STROKE_DASHED); - this.allCurves.forEach(g2d::draw); - - // reset - g2d.setTransform(tx_orig); - } - - private AffineTransform getDrawTransform() { - // ------ scale - double minX = extent[0].x, maxX = extent[1].x; - double minY = extent[0].y, maxY = extent[1].y; - - // we're scaling and respecting the proportions, check which scale to use - double sx = this.canvasWidth / Math.abs(maxX - minX); - double sy = this.canvasHeight / Math.abs(maxY - minY); - double s = Math.min(sx, sy); - - double m00, m11, m02, m12; - if (minX < maxX) { - m00 = s; - m02 = -s * minX; - } else { - // inverted X axis - m00 = -s; - m02 = this.canvasWidth + s * maxX; - } - if (minY < maxY) { - m11 = s; - m12 = -s * minY; - } else { - // inverted Y axis - m11 = -s; - m12 = this.canvasHeight + s * maxY; - } - - // scale to the available view port - AffineTransform scaleTransform = new AffineTransform(m00, 0, 0, m11, m02, m12); - - // invert the Y axis since (0, 0) is at top left for AWT - AffineTransform invertY = new AffineTransform(1, 0, 0, -1, 0, this.canvasHeight); - invertY.concatenate(scaleTransform); - - return invertY; - } - - public Dimension getSize(double dpi) { - double metricScalingFactor = 0.02539999969303608; - // 1 inch = 25,4 millimeter - final double factor = dpi * metricScalingFactor / 25.4; - - int width = (int) Math.ceil(Math.abs(extent[1].x - extent[0].x) * factor); - int height = (int) Math.ceil(Math.abs(extent[1].y - extent[0].y) * factor); - - return new Dimension(width, height); - } - - public void scale(double w, double h) { - double extentWidth = Math.abs(extent[1].x - extent[0].x); - double extentHeight = Math.abs(extent[1].y - extent[0].y); - - double fx = w / extentWidth; - if (fx * extentHeight > h) { - fx = h / extentHeight; - } - this.canvasWidth = (int) Math.round(fx * extentWidth); - this.canvasHeight = (int) Math.round(fx * extentHeight); - - // out.println("canvas scaled (" + canvasWidth + " x " + canvasHeight + ")"); - - this.isScaled = true; - } - - protected boolean checkImage(BufferedImage image) { - final AffineTransform tx = getDrawTransform(); - - final Point2D pMin = new Point2D.Double(bboxAllCurves.getMinX(), bboxAllCurves.getMinY()); - final Point2D pMax = new Point2D.Double(bboxAllCurves.getMaxX(), bboxAllCurves.getMaxY()); - - final Point2D tMin = tx.transform(pMin, null); - final Point2D tMax = tx.transform(pMax, null); - - int xMin = (int) tMin.getX(); - int xMax = (int) tMax.getX(); - if (xMin > xMax) { - int t = xMin; - xMin = xMax; - xMax = t; - } - - int yMin = (int) tMin.getY(); - int yMax = (int) tMax.getY(); - if (yMin > yMax) { - int t = yMin; - yMin = yMax; - yMax = t; - } - // add pixel margin (AA): - xMin -= 3; - xMax += 4; - yMin -= 3; - yMax += 4; - - if (xMin < 0 || xMax > image.getWidth() - || yMin < 0 || yMax > image.getHeight()) { - return true; - } - - // out.println("Checking rectangle: " + tMin + " to " + tMax); - // out.println("X min: " + xMin + " - max: " + xMax); - // out.println("Y min: " + yMin + " - max: " + yMax); - - final Raster raster = image.getData(); - final int expected = Color.WHITE.getRGB(); - int nBadPixels = 0; - - // horizontal lines: - for (int x = xMin; x <= xMax; x++) { - if (!checkPixel(raster, x, yMin, expected)) { - nBadPixels++; - } - if (!checkPixel(raster, x, yMax, expected)) { - nBadPixels++; - } - } - - // vertical lines: - for (int y = yMin; y <= yMax; y++) { - if (!checkPixel(raster, xMin, y, expected)) { - nBadPixels++; - } - if (!checkPixel(raster, xMax, y, expected)) { - nBadPixels++; - } - } - - if (nBadPixels != 0) { - out.println("(" + canvasWidth + " x " + canvasHeight + ") BAD pixels = " + nBadPixels); - - if (SAVE_IMAGE) { - try { - final File file = new File("Bug8341381-" + canvasWidth + "-" + canvasHeight + ".png"); - - out.println("Writing file: " + file.getAbsolutePath()); - ImageIO.write(image.getSubimage(0, 0, canvasWidth, canvasHeight), "PNG", file); - } catch (IOException ioe) { - ioe.printStackTrace(); - } - } - return false; - } else if (TRACE_ALL) { - out.println("(" + canvasWidth + " x " + canvasHeight + ") OK"); - } - return true; - } - - private final static int[] TMP_RGB = new int[1]; - - private static boolean checkPixel(final Raster raster, - final int x, final int y, - final int expected) { - - final int[] rgb = (int[]) raster.getDataElements(x, y, TMP_RGB); - - if (rgb[0] != expected) { - if (TRACE_CHECK_PIXELS) { - out.println("bad pixel at (" + x + ", " + y + ") = " + rgb[0] - + " expected = " + expected); - } - return false; - } - return true; - } - } -} diff --git a/test/jdk/sun/security/krb5/config/native/TestDynamicStore.java b/test/jdk/sun/security/krb5/config/native/TestDynamicStore.java index 0ee559f33e47b..7e396013a71ee 100644 --- a/test/jdk/sun/security/krb5/config/native/TestDynamicStore.java +++ b/test/jdk/sun/security/krb5/config/native/TestDynamicStore.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 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,15 +27,13 @@ * @summary SCDynamicStoreConfig works * @modules java.security.jgss/sun.security.krb5 * @library /test/lib - * @run main/manual/native/timeout=180 TestDynamicStore + * @run main/manual/native TestDynamicStore * @requires (os.family == "mac") */ import jdk.test.lib.Asserts; import sun.security.krb5.Config; -import javax.swing.JOptionPane; - // =================== Attention =================== // This test calls a native method implemented in libTestDynamicStore.m // to modify system-level Kerberos 5 settings stored in the dynamic store. @@ -58,17 +56,6 @@ static int action(char what, char whom) throws Exception { public static void main(String[] args) throws Exception { - // Show a popup to remind to run this test as sudo user - // this will only trigger if sudo (root) user is not detected - if (!"root".equals(System.getProperty("user.name"))) { - - JOptionPane.showMessageDialog(null, """ - This test MUST be run as ROOT.\s - Please close and RESTART the test."""); - - Asserts.assertFalse(true, "This test must be run as ROOT"); - } - System.loadLibrary("TestDynamicStore"); Config cfg = Config.getInstance(); diff --git a/test/jdk/sun/security/pkcs11/Cipher/TestKATForGCM.java b/test/jdk/sun/security/pkcs11/Cipher/TestKATForGCM.java index e5e8284e6f4ac..9844e8ecfd28f 100644 --- a/test/jdk/sun/security/pkcs11/Cipher/TestKATForGCM.java +++ b/test/jdk/sun/security/pkcs11/Cipher/TestKATForGCM.java @@ -321,19 +321,14 @@ public void main(Provider p) throws Exception { System.out.println("Test Passed!"); } } catch (Exception e) { - System.out.println("Exception occured using " + p.getName() - + " version " + p.getVersionStr()); + System.out.println("Exception occured using " + p.getName() + " version " + p.getVersionStr()); if (isNSS(p)) { - Version ver = getNSSInfo("nss"); + double ver = getNSSInfo("nss"); String osName = System.getProperty("os.name"); - - if (osName.equals("Linux") && - ver.major() == 3 && ver.minor() < 15 - && (ver.minor() > 13 && ver.patch() >= 9)) { + if (ver > 3.139 && ver < 3.15 && osName.equals("Linux")) { // warn about buggy behaviour on Linux with nss 3.14 - System.out.println("Warning: old NSS " + ver - + " might be problematic, consider upgrading it"); + System.out.println("Warning: old NSS " + ver + " might be problematic, consider upgrading it"); } } throw e; diff --git a/test/jdk/sun/security/pkcs11/KeyStore/SecretKeysBasic.java b/test/jdk/sun/security/pkcs11/KeyStore/SecretKeysBasic.java index 1ff80fcaf07f9..4d876604c0182 100644 --- a/test/jdk/sun/security/pkcs11/KeyStore/SecretKeysBasic.java +++ b/test/jdk/sun/security/pkcs11/KeyStore/SecretKeysBasic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2023, 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 @@ -116,14 +116,11 @@ private static boolean checkSecretKeyEntry(String alias, // A bug in NSS 3.12 (Mozilla bug 471665) causes AES key lengths // to be read incorrectly. Checking for improper 16 byte length // in key string. - if (isNSS(provider) && expected.getAlgorithm().equals("AES")) { - Version version = getNSSVersion(); - if (version.major() == 3 && version.minor() == 12 - && version.patch() <= 2) { - System.out.println("NSS 3.12 bug returns incorrect AES key " + - "length breaking key storage. Aborting..."); - return true; - } + if (isNSS(provider) && expected.getAlgorithm().equals("AES") && + (getNSSVersion() >= 3.12 && getNSSVersion() <= 3.122)) { + System.out.println("NSS 3.12 bug returns incorrect AES key "+ + "length breaking key storage. Aborting..."); + return true; } if (saveBeforeCheck) { @@ -171,7 +168,7 @@ private static void dumpKey(String info, SecretKey key) { private static void doTest() throws Exception { // Make sure both NSS libraries are the same version. if (isNSS(provider) && - (!getLibsoftokn3Version().equals(getLibnss3Version()))) { + (getLibsoftokn3Version() != getLibnss3Version())) { System.out.println("libsoftokn3 and libnss3 versions do not match. Aborting test..."); return; } diff --git a/test/jdk/sun/security/pkcs11/PKCS11Test.java b/test/jdk/sun/security/pkcs11/PKCS11Test.java index 98343d9b7e6d5..8454f3ac463e6 100644 --- a/test/jdk/sun/security/pkcs11/PKCS11Test.java +++ b/test/jdk/sun/security/pkcs11/PKCS11Test.java @@ -83,7 +83,7 @@ public abstract class PKCS11Test { private static final String NSS_BUNDLE_VERSION = "3.111"; private static final String NSSLIB = "jpg.tests.jdk.nsslib"; - static Version nss_version = null; + static double nss_version = -1; static ECCState nss_ecc_status = ECCState.Basic; // The NSS library we need to search for in getNSSLibDir() @@ -93,8 +93,8 @@ public abstract class PKCS11Test { // NSS versions of each library. It is simpler to keep nss_version // for quick checking for generic testing than many if-else statements. - static Version softoken3_version = null; - static Version nss3_version = null; + static double softoken3_version = -1; + static double nss3_version = -1; static Provider pkcs11 = newPKCS11Provider(); private static String PKCS11_BASE; private static Map osMap; @@ -269,29 +269,13 @@ private static String getOsId() { } static boolean isBadNSSVersion(Provider p) { - Version nssVersion = getNSSVersion(); - if (isNSS(p)) { - // bad version is just between [3.11,3.12) - return nssVersion.major == 3 && 11 == nssVersion.minor; - } else { - return false; + double nssVersion = getNSSVersion(); + if (isNSS(p) && nssVersion >= 3.11 && nssVersion < 3.12) { + System.out.println("NSS 3.11 has a DER issue that recent " + + "version do not, skipping"); + return true; } - } - - public record Version(int major, int minor, int patch) {} - - protected static Version parseVersionString(String version) { - String [] parts = version.split("\\."); - int major = Integer.parseInt(parts[0]); - int minor = 0; - int patch = 0; - if (parts.length >= 2) { - minor = Integer.parseInt(parts[1]); - } - if (parts.length >= 3) { - patch = Integer.parseInt(parts[2]); - } - return new Version(major, minor, patch); + return false; } protected static void safeReload(String lib) { @@ -320,26 +304,26 @@ public static boolean isNSS(Provider p) { return p.getName().equalsIgnoreCase("SUNPKCS11-NSS"); } - static Version getNSSVersion() { - if (nss_version == null) + static double getNSSVersion() { + if (nss_version == -1) getNSSInfo(); return nss_version; } static ECCState getNSSECC() { - if (nss_version == null) + if (nss_version == -1) getNSSInfo(); return nss_ecc_status; } - public static Version getLibsoftokn3Version() { - if (softoken3_version == null) + public static double getLibsoftokn3Version() { + if (softoken3_version == -1) return getNSSInfo("softokn3"); return softoken3_version; } - public static Version getLibnss3Version() { - if (nss3_version == null) + public static double getLibnss3Version() { + if (nss3_version == -1) return getNSSInfo("nss3"); return nss3_version; } @@ -354,7 +338,7 @@ static void getNSSInfo() { // $Header: NSS // Version: NSS // Here, stands for NSS version. - static Version getNSSInfo(String library) { + static double getNSSInfo(String library) { // look for two types of headers in NSS libraries String nssHeader1 = "$Header: NSS"; String nssHeader2 = "Version: NSS"; @@ -363,15 +347,15 @@ static Version getNSSInfo(String library) { int i = 0; Path libfile = null; - if (library.compareTo("softokn3") == 0 && softoken3_version != null) + if (library.compareTo("softokn3") == 0 && softoken3_version > -1) return softoken3_version; - if (library.compareTo("nss3") == 0 && nss3_version != null) + if (library.compareTo("nss3") == 0 && nss3_version > -1) return nss3_version; try { libfile = getNSSLibPath(); if (libfile == null) { - return parseVersionString("0.0"); + return 0.0; } try (InputStream is = Files.newInputStream(libfile)) { byte[] data = new byte[1000]; @@ -407,7 +391,7 @@ static Version getNSSInfo(String library) { if (!found) { System.out.println("lib" + library + " version not found, set to 0.0: " + libfile); - nss_version = parseVersionString("0.0"); + nss_version = 0.0; return nss_version; } @@ -420,7 +404,26 @@ static Version getNSSInfo(String library) { version.append(c); } - nss_version = parseVersionString(version.toString()); + // If a "dot dot" release, strip the extra dots for double parsing + String[] dot = version.toString().split("\\."); + if (dot.length > 2) { + version = new StringBuilder(dot[0] + "." + dot[1]); + for (int j = 2; dot.length > j; j++) { + version.append(dot[j]); + } + } + + // Convert to double for easier version value checking + try { + nss_version = Double.parseDouble(version.toString()); + } catch (NumberFormatException e) { + System.out.println("===== Content start ====="); + System.out.println(s); + System.out.println("===== Content end ====="); + System.out.println("Failed to parse lib" + library + + " version. Set to 0.0"); + e.printStackTrace(); + } System.out.print("library: " + library + ", version: " + version + ". "); diff --git a/test/jdk/sun/security/pkcs11/Secmod/AddTrustedCert.java b/test/jdk/sun/security/pkcs11/Secmod/AddTrustedCert.java index 7b4a5075da867..880adc954ea50 100644 --- a/test/jdk/sun/security/pkcs11/Secmod/AddTrustedCert.java +++ b/test/jdk/sun/security/pkcs11/Secmod/AddTrustedCert.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -121,10 +121,10 @@ public static void main(String[] args) throws Exception { } private static boolean improperNSSVersion(Provider p) { - Version nssVersion = getNSSVersion(); - if (p.getName().equalsIgnoreCase("SunPKCS11-NSSKeyStore")) { - return nssVersion.major() == 3 && - (nssVersion.minor() >= 28 && nssVersion.minor() < 35); + double nssVersion = getNSSVersion(); + if (p.getName().equalsIgnoreCase("SunPKCS11-NSSKeyStore") + && nssVersion >= 3.28 && nssVersion < 3.35) { + return true; } return false; diff --git a/test/jdk/sun/security/pkcs11/Signature/TestDSAKeyLength.java b/test/jdk/sun/security/pkcs11/Signature/TestDSAKeyLength.java index ffd7b9e3ee060..a9b43a647a9ad 100644 --- a/test/jdk/sun/security/pkcs11/Signature/TestDSAKeyLength.java +++ b/test/jdk/sun/security/pkcs11/Signature/TestDSAKeyLength.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,15 +47,13 @@ public static void main(String[] args) throws Exception { @Override protected boolean skipTest(Provider provider) { - if (isNSS(provider)) { - Version version = getNSSVersion(); - if (version == null) { - return true; - } - if (version.major() >= 3 && version.minor() >= 14){ - System.out.println("Skip testing NSS " + version); - return true; - } + double version = getNSSVersion(); + String[] versionStrs = Double.toString(version).split("\\."); + int major = Integer.parseInt(versionStrs[0]); + int minor = Integer.parseInt(versionStrs[1]); + if (isNSS(provider) && (version == 0.0 || (major >= 3 && minor >= 14))) { + System.out.println("Skip testing NSS " + version); + return true; } return false; diff --git a/test/jdk/sun/security/pkcs11/ec/TestECDH.java b/test/jdk/sun/security/pkcs11/ec/TestECDH.java index 2900656f6261e..b6821b8837212 100644 --- a/test/jdk/sun/security/pkcs11/ec/TestECDH.java +++ b/test/jdk/sun/security/pkcs11/ec/TestECDH.java @@ -111,7 +111,6 @@ protected boolean skipTest(Provider p) { * PKCS11Test.main will remove this provider if needed */ Providers.setAt(p, 1); - System.out.println("Testing provider " + p.getName()); if (false) { KeyPairGenerator kpg = KeyPairGenerator.getInstance("EC", p); diff --git a/test/jdk/sun/security/provider/certpath/DisabledAlgorithms/CPValidatorTrustAnchor.java b/test/jdk/sun/security/provider/certpath/DisabledAlgorithms/CPValidatorTrustAnchor.java index d74d712d8d749..63eaa12b00c0e 100644 --- a/test/jdk/sun/security/provider/certpath/DisabledAlgorithms/CPValidatorTrustAnchor.java +++ b/test/jdk/sun/security/provider/certpath/DisabledAlgorithms/CPValidatorTrustAnchor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,35 +31,19 @@ * @summary Disable MD2 support * new CertPathValidatorException.BasicReason enum constant for * constrained algorithm - * @enablePreview * @run main/othervm CPValidatorTrustAnchor * @author Xuelei Fan */ -import java.io.ByteArrayInputStream; -import java.security.PEMDecoder; +import java.io.*; +import java.net.SocketException; +import java.util.*; import java.security.Security; -import java.security.cert.CertPath; -import java.security.cert.CertPathValidator; -import java.security.cert.CertPathValidatorException; -import java.security.cert.CertPathValidatorException.BasicReason; -import java.security.cert.Certificate; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.PKIXParameters; -import java.security.cert.TrustAnchor; -import java.security.cert.X509Certificate; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Collections; -import java.util.Date; -import java.util.List; -import java.util.Set; +import java.security.cert.*; +import java.security.cert.CertPathValidatorException.*; public class CPValidatorTrustAnchor { - private static final PEMDecoder pemDecoder = java.security.PEMDecoder.of(); - static String selfSignedCertStr = null; // SHA1withRSA 1024 @@ -120,26 +104,33 @@ public class CPValidatorTrustAnchor { private static CertPath generateCertificatePath() throws CertificateException { - + // generate certificate from cert strings CertificateFactory cf = CertificateFactory.getInstance("X.509"); - // generate certificate from cert strings - Certificate selfSignedCert = pemDecoder.decode(selfSignedCertStr, X509Certificate.class); + ByteArrayInputStream is; + + is = new ByteArrayInputStream(selfSignedCertStr.getBytes()); + Certificate selfSignedCert = cf.generateCertificate(is); // generate certification path - List list = Collections.singletonList(selfSignedCert); + List list = Arrays.asList(new Certificate[] { + selfSignedCert}); return cf.generateCertPath(list); } - private static Set generateTrustAnchors() { - + private static Set generateTrustAnchors() + throws CertificateException { // generate certificate from cert string - X509Certificate selfSignedCert = pemDecoder.decode(selfSignedCertStr, X509Certificate.class); + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + + ByteArrayInputStream is = + new ByteArrayInputStream(selfSignedCertStr.getBytes()); + Certificate selfSignedCert = cf.generateCertificate(is); // generate a trust anchor TrustAnchor anchor = - new TrustAnchor(selfSignedCert, null); + new TrustAnchor((X509Certificate)selfSignedCert, null); return Collections.singleton(anchor); } @@ -173,7 +164,7 @@ public static void main(String args[]) throws Exception { } private static void validate(String trustAnchor) - throws Exception { + throws CertPathValidatorException, Exception { selfSignedCertStr = trustAnchor; CertPath path = generateCertificatePath(); @@ -185,11 +176,7 @@ private static void validate(String trustAnchor) params.setRevocationEnabled(false); // set the validation time - final Calendar calendar = Calendar.getInstance(); - calendar.set(Calendar.YEAR, 2009); - calendar.set(Calendar.MONTH, 9); - calendar.set(Calendar.DATE, 1); - params.setDate(calendar.getTime()); // 2009-09-01 + params.setDate(new Date(109, 9, 1)); // 2009-09-01 CertPathValidator validator = CertPathValidator.getInstance("PKIX"); diff --git a/test/jdk/sun/security/rsa/InvalidBitString.java b/test/jdk/sun/security/rsa/InvalidBitString.java index 7f8408f35f0bf..be9e42ca5444f 100644 --- a/test/jdk/sun/security/rsa/InvalidBitString.java +++ b/test/jdk/sun/security/rsa/InvalidBitString.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -23,15 +23,15 @@ /* @test * @summary Validation of signatures succeed when it should fail - * @enablePreview * @bug 6896700 */ -import java.security.PEMDecoder; +import java.io.InputStream; +import java.io.ByteArrayInputStream; import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; import java.security.PublicKey; import java.security.SignatureException; -import java.security.cert.X509Certificate; public class InvalidBitString { @@ -87,16 +87,16 @@ public class InvalidBitString { "ZAM6mgkuSY7/vdnsiJtU\n" + "-----END CERTIFICATE-----\n"; - public static void main(String[] args) throws Exception { - final PEMDecoder pemDecoder = PEMDecoder.of(); - Certificate signer = pemDecoder.decode(signerCertStr, X509Certificate.class); + public static void main(String args[]) throws Exception { + + Certificate signer = generate(signerCertStr); // the valid certificate - Certificate normal = pemDecoder.decode(normalCertStr, X509Certificate.class); + Certificate normal = generate(normalCertStr); // the invalid certificate with extra signature bits - Certificate longer = pemDecoder.decode(longerCertStr, X509Certificate.class); + Certificate longer = generate(longerCertStr); // the invalid certificate without enough signature bits - Certificate shorter = pemDecoder.decode(shorterCertStr, X509Certificate.class); + Certificate shorter = generate(shorterCertStr); if (!test(normal, signer, " normal", true) || !test(longer, signer, " longer", false) || @@ -105,6 +105,19 @@ public static void main(String[] args) throws Exception { } } + private static Certificate generate(String certStr) throws Exception { + InputStream is = null; + try { + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + is = new ByteArrayInputStream(certStr.getBytes()); + return cf.generateCertificate(is); + } finally { + if (is != null) { + is.close(); + } + } + } + private static boolean test(Certificate target, Certificate signer, String title, boolean expected) throws Exception { System.out.print("Checking " + title + ": expected: " + diff --git a/test/jdk/sun/security/ssl/ClientHandshaker/RSAExport.java b/test/jdk/sun/security/ssl/ClientHandshaker/RSAExport.java index 26d5c69e21986..698bbdf88b1a0 100644 --- a/test/jdk/sun/security/ssl/ClientHandshaker/RSAExport.java +++ b/test/jdk/sun/security/ssl/ClientHandshaker/RSAExport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2017, 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 @@ /* * @test * @bug 6690018 - * @enablePreview * @summary RSAClientKeyExchange NullPointerException * @run main/othervm RSAExport */ @@ -198,24 +197,17 @@ * */ -import java.io.InputStream; -import java.io.OutputStream; -import java.security.PEMDecoder; +import java.io.*; +import java.net.*; import java.security.Security; import java.security.KeyStore; import java.security.KeyFactory; import java.security.cert.Certificate; -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLServerSocket; -import javax.net.ssl.SSLServerSocketFactory; -import javax.net.ssl.SSLSocket; -import javax.net.ssl.SSLSocketFactory; -import javax.net.ssl.TrustManagerFactory; +import java.security.cert.CertificateFactory; +import java.security.spec.*; +import java.security.interfaces.*; +import javax.net.ssl.*; import java.math.BigInteger; -import java.security.cert.X509Certificate; -import java.security.interfaces.RSAPrivateKey; -import java.security.spec.RSAPrivateKeySpec; public class RSAExport { @@ -320,7 +312,7 @@ public class RSAExport { /* * Turn on SSL debugging? */ - static boolean debug = Boolean.getBoolean("test.debug"); + static boolean debug = false; /* * If the client or server is doing some kind of object creation @@ -394,7 +386,7 @@ void doClientSide() throws Exception { // Enable RSA_EXPORT cipher suites only. try { - String[] enabledSuites = { + String enabledSuites[] = { "SSL_RSA_EXPORT_WITH_RC4_40_MD5", "SSL_RSA_EXPORT_WITH_DES40_CBC_SHA"}; sslSocket.setEnabledCipherSuites(enabledSuites); @@ -479,20 +471,22 @@ public static void main(String[] args) throws Exception { void startServer(boolean newThread) throws Exception { if (newThread) { - serverThread = new Thread(() -> { - try { - doServerSide(); - } catch (Exception e) { - /* - * Our server thread just died. - * - * Release the client, if not active already... - */ - System.err.println("Server died..." + e); - serverReady = true; - serverException = e; + serverThread = new Thread() { + public void run() { + try { + doServerSide(); + } catch (Exception e) { + /* + * Our server thread just died. + * + * Release the client, if not active already... + */ + System.err.println("Server died..." + e); + serverReady = true; + serverException = e; + } } - }); + }; serverThread.start(); } else { doServerSide(); @@ -501,17 +495,19 @@ void startServer(boolean newThread) throws Exception { void startClient(boolean newThread) throws Exception { if (newThread) { - clientThread = new Thread(() -> { - try { - doClientSide(); - } catch (Exception e) { - /* - * Our client thread just died. - */ - System.err.println("Client died..."); - clientException = e; + clientThread = new Thread() { + public void run() { + try { + doClientSide(); + } catch (Exception e) { + /* + * Our client thread just died. + */ + System.err.println("Client died..."); + clientException = e; + } } - }); + }; clientThread.start(); } else { doClientSide(); @@ -521,10 +517,11 @@ void startClient(boolean newThread) throws Exception { // Get the SSL context private SSLContext getSSLContext(boolean authnRequired) throws Exception { // generate certificate from cert string + CertificateFactory cf = CertificateFactory.getInstance("X.509"); - final PEMDecoder pemDecoder = PEMDecoder.of(); - - Certificate trustedCert = pemDecoder.decode(trusedCertStr, X509Certificate.class); + ByteArrayInputStream is = + new ByteArrayInputStream(trusedCertStr.getBytes()); + Certificate trustedCert = cf.generateCertificate(is); // create a key store KeyStore ks = KeyStore.getInstance("JKS"); @@ -543,7 +540,8 @@ private SSLContext getSSLContext(boolean authnRequired) throws Exception { (RSAPrivateKey)kf.generatePrivate(priKeySpec); // generate certificate chain - Certificate serverCert = pemDecoder.decode(serverCertStr, X509Certificate.class); + is = new ByteArrayInputStream(serverCertStr.getBytes()); + Certificate serverCert = cf.generateCertificate(is); Certificate[] chain = new Certificate[2]; chain[0] = serverCert; diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/BasicConstraints.java b/test/jdk/sun/security/ssl/X509TrustManagerImpl/BasicConstraints.java index 051c940b3b080..7f9573a8eebe1 100644 --- a/test/jdk/sun/security/ssl/X509TrustManagerImpl/BasicConstraints.java +++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/BasicConstraints.java @@ -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 @@ -31,33 +31,20 @@ * @bug 7166570 * @summary JSSE certificate validation has started to fail for * certificate chains - * @enablePreview * @run main/othervm BasicConstraints PKIX * @run main/othervm BasicConstraints SunX509 */ -import java.io.InputStream; -import java.io.OutputStream; -import java.security.PEMDecoder; -import java.security.cert.CertPath; -import java.security.cert.CertPathValidator; -import java.security.cert.Certificate; -import java.security.cert.CertificateFactory; -import java.security.cert.PKIXParameters; -import java.security.cert.X509Certificate; -import java.security.interfaces.RSAPrivateKey; -import java.security.spec.PKCS8EncodedKeySpec; -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLServerSocket; -import javax.net.ssl.SSLServerSocketFactory; -import javax.net.ssl.SSLSocket; -import javax.net.ssl.SSLSocketFactory; -import javax.net.ssl.TrustManagerFactory; +import java.util.*; +import java.io.*; +import javax.net.ssl.*; import java.security.KeyStore; import java.security.KeyFactory; +import java.security.cert.*; +import java.security.spec.*; +import java.security.interfaces.*; -import java.util.Arrays; +import java.util.Base64; public class BasicConstraints { @@ -109,6 +96,33 @@ public class BasicConstraints { "cwIDUWqQda62xV7ChkTh7ia3uvBXob2iiB0aI3gVTTqDfK9F5XXtW4BXfqx0hvwB\n" + "6JzgmNyDQos=\n" + "-----END CERTIFICATE-----"; + static String trustedPrivateKey = // Private key in the format of PKCS#8 + "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDUJ3hT/9jY/i8i\n" + + "70EEaL6mbrhhdg/Ys1E0r97n+dZaY0olqkIBhh1r8UkKWtvOkj8WBFQ0sz0HhSjT\n" + + "rkVEisGLW+7zPJiDBPtQrRawvCDpnzUofnQ98zQKUTHji1OqhxgNzsKCy9vIh5Mh\n" + + "tX0CdGUScEDXlYUkAkxMKCVo2V5dRn34D+1rNGEeWxGnQ5vyPi0IwlpEOkYxhPLV\n" + + "dsb5aoLzBc/rdrrdzCM+svm7O38LhbVuA0F9NHAgdJRKE2F91ztkk1KvY0U9zCh1\n" + + "3u5WV7kl481qDujKGM4UURoEarbV2Xr+jNVGSpJZYCLU/sxFrL15iPeYtmJlovo2\n" + + "VbFed/NXAgMBAAECggEAUZvlQ5q1VbNhenTCc+m+/NK2hncd3WQNJtFIU7/dXuO2\n" + + "0ApQXbmzc6RbTmppB2tmbRe5NJSGM3BbpiHxb05Y6TyyDEsQ98Vgz0Xl5pJXrsaZ\n" + + "cjxChtoY+KcHI9qikoRpElaoqBu3LcpJJLxlnB4eCxu3NbbEgneH1fvTeCO1kvcp\n" + + "i3DDdyfY7WB9RW1yWAveiuqvtnbsPfJJLKEhFvZL2ArYCRTm/oIw64yukNe/QLR5\n" + + "bGzEJMT2ZNQMld1f+CW9tOrUKrnnPCGfMa351T5we+8B6sujWfftPutgEVx5TmHs\n" + + "AOW1SntMapbgg46K9EC/C5YQa5D1aNOH9ZTEMkgUMQKBgQDrpPQIHFozeeyZ0iiq\n" + + "HtReLPcqpkwr/9ELc3SjgUypSvpu0l/m++um0yLinlXMn25km/BP6Mv3t/+1uzAc\n" + + "qpopkcyek8X1hzNRhDkWuMv4KDOKk5c6qLx8FGSm6q8PYm5KbsiyeCM7CJoeoqJ5\n" + + "74IZjOIw7UrYLckCb6W8xGQLIwKBgQDmew3vGRR3JmCCSumtJQOqhF6bBYrNb6Qc\n" + + "r4vrng+QhNIquwGqHKPorAI1J8J1jOS+dkDWTxSz2xQKQ83nsOspzVPskpDh5mWL\n" + + "gGk5QCkX87jFsXfhvZFLksZMbIdpWze997Zs2fe/PWfPaH6o3erqo2zAhQV0eA9q\n" + + "C7tfImREPQKBgQDi2Xq/8CN52M9IScQx+dnyC5Gqckt0NCKXxn8sBIa7l129oDMI\n" + + "187FXA8CYPEyOu14V5KiKvdos66s0daAUlB04lI8+v+g3ZYuzH50/FQHwxPTPUBi\n" + + "DRzeyncXJWiAA/8vErWM8hDgfOh5w5Fsl4EEfdcmyNm7gWA4Qyknr1ysRwKBgQDC\n" + + "JSPepUy09VHUTxA59nT5HRmoEeoTFRizxTfi2LkZrphuwCotxoRXiRUu+3f1lyJU\n" + + "Qb5qCCFTQ5bE8squgTwGcVxhajC66V3ePePlAuPatkWN2ek28X1DoLaDR+Rk3h69\n" + + "Wb2EQbNMl4grkUUoMA8jaVhBb4vhyQSK+qjyAUFerQKBgQDXZPuflfsjH/d/O2yw\n" + + "qZbssKe9AKORjv795teblAc3vmsSlNwwVnPdS2aq1LHyoNbetc/OaZV151hTQ/9z\n" + + "bsA48oOojgrDD07Ovg3uDcNEIufxR0aGeSSvqhElp1r7wAYj8bAr6W/RH6MS16WW\n" + + "dRd+PH6hsap8BD2RlVCnrT3vIQ=="; // Certificate information: // Issuer: C=US, O=Java, OU=SunJSSE Test Serivce @@ -142,6 +156,33 @@ public class BasicConstraints { "P0QqaqP+xJIY+sRrzdckxSfS9AOOrJk2VXY8qEoxCN4wCvHJWuHEAF/Lm65d/hq3\n" + "2Uh8P+QHLeuEwF8RoTpjiGM9dXvaqcQz7w5G\n" + "-----END CERTIFICATE-----"; + static String caSignerPrivateKey = // Private key in the format of PKCS#8 + "MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDAvGeLKlW1ljae\n" + + "eu8NvDCjfW5BNK2c0C4ry7Is+1mM4PC7FA4bRpMaQHKIjLsZ5D1hoA9183cv3p1a\n" + + "P75/ZYMOyx1id/hXmbd3jp8BR0wbvrKxa53+4lO0S5AL5dOpU2AVhcdeQ7+DwoL6\n" + + "iAuHqNcABg3CijrIcFeZHcPMwaZMd9YxJG6YrnNHMWjbXTGKpma02NMB1UnRxsdN\n" + + "phqfRt2gkUs18l6697sSJ7eblvSWEWw1Bmtrg9No28UUsiF8q0m9i/G0QzYOrS6v\n" + + "ghum5bpHAixxfA9Z/ozHrN8gf8gNDTRnG6phDwVb1Uj9nO2f9yTArx7Kz5EtRNmD\n" + + "x9SNMS9rAgMBAAECggEAZk6cF/8s5+sIqy9OXdgbaW1XbT1tOuQ23gCOX9o8Os/c\n" + + "eTG4GzpnM3QqV9l8J85D1uKD0nSeO8bLd/CGSlG0M9IVkwNjy/xIqyoFtUQHXmLn\n" + + "r84UXAv/qqDBoc8pf6RGSKZuodcMfgBuTlaQ6D3zgou0GiQN9//KP/jQyouwnr3A\n" + + "LyXQekxriwPuSYAPak8s5XLfugOebbSRm2UdGEgX3yrT9FVu9rtgeMKdRaCOU8T4\n" + + "G2UdpGaiDfm5yrR+2XEIv4oaH3WFxmmfQCxVcOFJ1iRvfKBbLb1UCgtJuCBD067y\n" + + "dq5PrwUTeAvd7hwZd0lxCSnWY7VvYFNr7iJfyElowQKBgQD8eosot+Th03hpkYDs\n" + + "BIVsw7oqhJmcrPV1bSZ+aQwqqrOGypNmb7nLGTC8Cj1sT+EzfGs7GqxiLOEn4NXr\n" + + "TYV//RUPBSEXVp2y+2dot1a9oq0BJ8FwGTYL0qSwJrIXJfkQFrYhVVz3JLIWJbwV\n" + + "cy4YCQr094BhXTS7joJOUDRsYwKBgQDDbI3Lv+bBK8lLfIBll1RY1k5Gqy/H+qxp\n" + + "sMN8FmadmIGzHhe9xml6b5EfAZphAUF4vZJhQXloT5Wm+NNIAf6X6dRjvzyw7N9B\n" + + "d48EFJF4ChqNGBocsQRNr2wPRzQ+k2caw9YyYMIjbhktDzO1U/FJGYW6/Vgr2v4K\n" + + "siROnXfLWQKBgBOVAZQP5z2opC8z7NbhZuPPrnG7xRpEw+jupUyqoxnwEWqD7bjF\n" + + "M5jQBFqhRLBQ5buTi9GSuQoIRxJLuuu8IH2TyH1YvX9M5YBLRXL2vVCJ/HcZeURT\n" + + "gECcfs92wNtQw6d+y3N8ZnB4tSNIm/Th8RJGKUZkp91lWECvxeWDDP3XAoGASfNq\n" + + "NRAJYlAPfGFAtTDu2i8+r79X9XUGiXg6gVp4umpbqkxY75eFkq9lWzZgFRVEkUwr\n" + + "eGIubyquluDSEw2uKg5yMMzNSqZYVY3IsOKXqbUpFvtn5jOWTU90tNNdEdD100sI\n" + + "Y0f6Ly4amNKH3rZFOERQNtJn6zCTsbh3xMgR7QECgYBhQTqxLU5eIu38MKobzRue\n" + + "RoUkMcoY3DePkKPSYjilFhkUDozIXf/xUGnB8kERZKO+44wUkuPGljiFL1/P/RO9\n" + + "zhHAV94Kw2ddtfxy05GVtUZ99miBmsMb2m8vumGJqfR8h2xpfc1Ra0zfrsPgLNru\n" + + "xDTDW+bNbM7XyPvg9mOf7Q=="; // Certificate information: // Issuer: C=US, O=Java, OU=SunJSSE Test Serivce, CN=casigner @@ -175,6 +216,33 @@ public class BasicConstraints { "zr4da2aIg9CKrH2QWoMkDfRKkJvrU3/VhVfVWpNbXFE2xZXftQl3hpFCJ3FkpciA\n" + "l3hKeq4byY3LXxhAClHpk1KkXJkMnQdOfA5aGekj/Cjuaz1/iKYAG2vRq7YcuM/o\n" + "-----END CERTIFICATE-----"; + static String certIssuerPrivateKey = // Private key in the format of PKCS#8 + "MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQC1lDVpzmzwbKOL\n" + + "yFWkjPjqtX9xLMq7SVqobvhBv+VChMGGjQbNQPbtczOcXNOcuMFyXxY++eXY7c37\n" + + "MzhbdZHv4Y4aWEn+A3EiX2/fTAbxx165qxKiHbD2EmlKk/Q6yIvi9M9EXXr/viEC\n" + + "Y4/Sdtd4KYtfETa0FpfF5/ZpZMYQo8I9RqBQOmhfvXL1l/Lodla5elZtvIUyp5k2\n" + + "nRQe58AxeP5hrilbIgfmEySf9mOkaTalRf2epBE/wRNA7Qi5Sr2O4pY2x3PPdmMy\n" + + "NL4cZaOJTgdyeDYbEMSW6vpiJW26ma/qeFgPIXZ8COFJZLSOEu310M4QOdSR1Y2c\n" + + "l3/V2E0VAgMBAAECggEBAJjfVrjl2kHwtSCSYchQB6FTfSBDnctgTrtP8iMo9FO0\n" + + "gVpOkVNtRndTbjhOzro7smIgPBJ5QlIIpErBLMmTinJza7gybNk2/KD7yKwuzgnw\n" + + "2IdoyB9E8B+8EHmBZzW2ck953KaqLUvzPsdMG2IOPAomr/gx/eRQwScVzBefiEGo\n" + + "sN+rGfUt/RNAHwWje1KuNDj21S84agQhN6hdYUnIMsvJLu/9mOwUb9ff+AzTUfFr\n" + + "zyx2MJL4Cx59DkUUMESCfinlHUc21llQjFWmX/zOoGY0X0qV/YM/GRsv1ZDFHw9o\n" + + "hQ6m8Ov7D9wB3TKZBI97sCyggjBfSeuYQlNbs99KWQECgYEA7IKNL0ME7FuIrKYu\n" + + "FCQ/Duz1N3oQXLzrTGKUSU1qSbrU2Jwk4SfJ8ZYCW1TP6vZkaQsTXmXun3yyCAqZ\n" + + "hcOtDBhI+b7Wpmmyf6nb83oYJtzHMRQZ5qS+9vOBfV9Uf1za8XI4p90EqkFHByCF\n" + + "tHfjVbjK39zN4CvaO3tqpOaYtL0CgYEAxIrTAhGWy9nBsxf8QeqDou0rV5Cw50Kl\n" + + "kQsE7KLmjvrMaFFpUc5lgWoC+pm/69VpNBUuN/38YozwxVjVi/nMJuuK150mhdWI\n" + + "B28FI7ORnFmVeSvTrP4mBX1ct2Tny9zpchXn3rpHR5NZUs7oBhjudHSfRMrHxeBs\n" + + "Kv2pr2s6uzkCgYAtrEh3iAm7WzHZpX3ghd9nknsIa5odTp5h8eeRAFI2Ss4vxneY\n" + + "w4ZMERwDZy1/wnVBk9H5uNWMFxiKVQGww0j3vPjawe/R0zeVT8gaDMn9N0WARNF7\n" + + "qPT3265196LptZTSa6xlPllYR6LfzXgEkeJk+3qyIIHheJZ8RikiDyYOQQKBgQC/\n" + + "rxlegiMNC4KDldf7vanGxAKqcz5lPbXWQOX7mGC+f9HNx+Cs3VxYHDltiXgJnOju\n" + + "191s1HRK9WR5REt5KhY2uzB9WxJQItJ5VYiwqhhQYXqLY/gdVv1kC0DayDndtMWk\n" + + "88JhklGkeAv83DikgbpGr9sJr6+oyFkWkLDmmfD82QKBgQCMgkZJzrdSNNlB0n5x\n" + + "xC3MzlsQ5aBJuUctnMfuyDi+11yLAuP1oLzGEJ7qEfFoGRO0V8zJWmHAfNhmVYEX\n" + + "ow5g0WbPT16GoRCiOAzq+ewH+TEELMF6HWqnDuTnCg28Jg0dw2kdVTqeyzKOQlLG\n" + + "ua9c2DY3PUTXQPNqLVhz+XxZKA=="; // Certificate information: // Issuer: C=US, O=Java, OU=SunJSSE Test Serivce, CN=certissuer @@ -209,7 +277,6 @@ public class BasicConstraints { "u/inkyf8NcG7zLBJJyuKfUXO/OzGPD5QMviVc+PCGTY=\n" + "-----END CERTIFICATE-----"; static String serverPrivateKey = // Private key in the format of PKCS#8 - "-----BEGIN PRIVATE KEY-----\n" + "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCaDgoxN2UQQero\n" + "oBQ4JlQP1BFaZEtIkdIU2VJs4whz85J0LSB/68iEOS5e8wCz9wiQWr4isor7sl3e\n" + "B2dnLGY28BthOTw2j/CYw/dRqyDbPZniooB233uLGarKjqQWXpRFQi6bgEQmNqWe\n" + @@ -235,8 +302,7 @@ public class BasicConstraints { "/RiupLD4/awmf21ytpfHcmOWCcdQoE4WC69a6VyVAoGAboeogM5/TRKj80rXfUH2\n" + "lFZzgX246XGwNyOVVgOuv/Oxa61b5FeeCpnFQcjpZmC5vd63X3w7oYSDe2wUt+Wh\n" + "LhYunmcCEj+yb3of33loQb/FM2OLW9UoQakB7ewio9vtw+BAnWxnHFkEaqdxMXpy\n" + - "TiSXLpQ1Q9GvDpzngDzJzzY=\n" + - "-----END PRIVATE KEY-----"; + "TiSXLpQ1Q9GvDpzngDzJzzY="; // Certificate information: // Issuer: C=US, O=Java, OU=SunJSSE Test Serivce, CN=certissuer @@ -271,7 +337,6 @@ public class BasicConstraints { "tL85OZz8ov7d2jVet/w7FD4M5XfcogsNtpX4kaMsctyvQbDYRA==\n" + "-----END CERTIFICATE-----"; static String clientPrivateKey = // Private key in the format of PKCS#8 - "-----BEGIN PRIVATE KEY-----\n" + "MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDFwNzVfqQ58J0I\n" + "FxUO1ng7XE3uKg0FfbQ4/XEWRakF6PeAt9JZLl83R++tW2QfOAxEldKiyJOv5/g/\n" + "UjrIO0j3u7noxtuK6Yf1aTwDaz16PI8cIfylvvMtKWDYoBVGQ4vphAwDhoMqmgG2\n" + @@ -297,10 +362,9 @@ public class BasicConstraints { "cWJdYS5BrwEUen8vaQt1LhgS6lOqYsjysCxkYm078QKBgEJuq4RzecgiGx8srWDb\n" + "pQKpxrdEt82Y7OXLVj+W9vixcW/xUYhDYGsfdUigZoOjo4nV8KVmMbuI48PIYwnw\n" + "haLwWrBWlki4x9MRwuZUdewOYoo7hDZToZmIDescdiwv8CA/Dg9kOX3YYLPW+cWl\n" + - "i1pnyMPaloBOhz3Y07sWXxCz\n" + - "-----END PRIVATE KEY-----"; + "i1pnyMPaloBOhz3Y07sWXxCz"; - static char[] passphrase = "passphrase".toCharArray(); + static char passphrase[] = "passphrase".toCharArray(); /* * Is the server ready to serve? @@ -310,7 +374,7 @@ public class BasicConstraints { /* * Turn on SSL debugging? */ - static boolean debug = Boolean.getBoolean("test.debug"); + static boolean debug = false; /* * Define the server side of the test. @@ -383,39 +447,48 @@ void doClientSide() throws Exception { // get the ssl context private static SSLContext getSSLContext(boolean isServer) throws Exception { - final PEMDecoder pemDecoder = PEMDecoder.of(); + // generate certificate from cert string + CertificateFactory cf = CertificateFactory.getInstance("X.509"); // create a key store KeyStore ks = KeyStore.getInstance("JKS"); ks.load(null, null); - // generate certificate from cert string - - Certificate trusedCert = pemDecoder.decode(trusedCertStr, X509Certificate.class); - // import the trused cert + ByteArrayInputStream is = + new ByteArrayInputStream(trusedCertStr.getBytes()); + Certificate trusedCert = cf.generateCertificate(is); + is.close(); + ks.setCertificateEntry("SunJSSE Test Serivce", trusedCert); // import the certificate chain and key Certificate[] chain = new Certificate[3]; - Certificate caSignerCert =pemDecoder.decode(caSignerStr, X509Certificate.class); + is = new ByteArrayInputStream(caSignerStr.getBytes()); + Certificate caSignerCert = cf.generateCertificate(is); + is.close(); chain[2] = caSignerCert; - Certificate certIssuerCert =pemDecoder.decode(certIssuerStr, X509Certificate.class); + is = new ByteArrayInputStream(certIssuerStr.getBytes()); + Certificate certIssuerCert = cf.generateCertificate(is); + is.close(); chain[1] = certIssuerCert; - PKCS8EncodedKeySpec priKeySpec; - Certificate keyCert; + PKCS8EncodedKeySpec priKeySpec = null; if (isServer) { - priKeySpec =pemDecoder.decode(serverPrivateKey, PKCS8EncodedKeySpec.class); - keyCert = pemDecoder.decode(serverCertStr, X509Certificate.class); + priKeySpec = new PKCS8EncodedKeySpec( + Base64.getMimeDecoder().decode(serverPrivateKey)); + is = new ByteArrayInputStream(serverCertStr.getBytes()); } else { - priKeySpec = pemDecoder.decode(clientPrivateKey, PKCS8EncodedKeySpec.class); - keyCert = pemDecoder.decode(clientCertStr, X509Certificate.class); + priKeySpec = new PKCS8EncodedKeySpec( + Base64.getMimeDecoder().decode(clientPrivateKey)); + is = new ByteArrayInputStream(clientCertStr.getBytes()); } KeyFactory kf = KeyFactory.getInstance("RSA"); RSAPrivateKey priKey = (RSAPrivateKey)kf.generatePrivate(priKeySpec); + Certificate keyCert = cf.generateCertificate(is); + is.close(); chain[0] = keyCert; ks.setKeyEntry("End Entity", priKey, passphrase, chain); @@ -423,8 +496,7 @@ private static SSLContext getSSLContext(boolean isServer) throws Exception { // check the certification path PKIXParameters paras = new PKIXParameters(ks); paras.setRevocationEnabled(false); - CertPath path = CertificateFactory.getInstance("X.509") - .generateCertPath(Arrays.asList(chain)); + CertPath path = cf.generateCertPath(Arrays.asList(chain)); CertPathValidator cv = CertPathValidator.getInstance("PKIX"); cv.validate(path, paras); @@ -459,7 +531,7 @@ private static void parseArguments(String[] args) { volatile Exception serverException = null; volatile Exception clientException = null; - public static void main(String[] args) throws Exception { + public static void main(String args[]) throws Exception { if (debug) System.setProperty("javax.net.debug", "all"); @@ -514,20 +586,22 @@ public static void main(String[] args) throws Exception { void startServer(boolean newThread) throws Exception { if (newThread) { - serverThread = new Thread(() -> { - try { - doServerSide(); - } catch (Exception e) { - /* - * Our server thread just died. - * - * Release the client, if not active already... - */ - System.err.println("Server died..."); - serverReady = true; - serverException = e; + serverThread = new Thread() { + public void run() { + try { + doServerSide(); + } catch (Exception e) { + /* + * Our server thread just died. + * + * Release the client, if not active already... + */ + System.err.println("Server died..."); + serverReady = true; + serverException = e; + } } - }); + }; serverThread.start(); } else { doServerSide(); @@ -536,17 +610,19 @@ void startServer(boolean newThread) throws Exception { void startClient(boolean newThread) throws Exception { if (newThread) { - clientThread = new Thread(() -> { - try { - doClientSide(); - } catch (Exception e) { - /* - * Our client thread just died. - */ - System.err.println("Client died..."); - clientException = e; + clientThread = new Thread() { + public void run() { + try { + doClientSide(); + } catch (Exception e) { + /* + * Our client thread just died. + */ + System.err.println("Client died..."); + clientException = e; + } } - }); + }; clientThread.start(); } else { doClientSide(); diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/ComodoHacker.java b/test/jdk/sun/security/ssl/X509TrustManagerImpl/ComodoHacker.java index f1e5415e2c3bb..6a67364360f4f 100644 --- a/test/jdk/sun/security/ssl/X509TrustManagerImpl/ComodoHacker.java +++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/ComodoHacker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,18 +25,21 @@ * @test * @bug 7123519 * @summary Problem with java/classes_security - * @enablePreview * @run main/othervm ComodoHacker PKIX * @run main/othervm ComodoHacker SunX509 */ -import javax.net.ssl.TrustManagerFactory; -import javax.net.ssl.X509TrustManager; +import java.net.*; +import java.util.*; +import java.io.*; +import javax.net.ssl.*; import java.security.KeyStore; -import java.security.PEMDecoder; import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.security.cert.CertificateException; +import java.security.spec.*; +import java.security.interfaces.*; public class ComodoHacker { // DigiNotar Root CA, untrusted root certificate @@ -210,8 +213,6 @@ public class ComodoHacker { "baB2sVGcVNBkK55bT8gPqnx8JypubyUvayzZGg==\n" + "-----END CERTIFICATE-----"; - private static final PEMDecoder pemDecoder = PEMDecoder.of(); - private static String tmAlgorithm; // trust manager public static void main(String args[]) throws Exception { @@ -252,15 +253,19 @@ private static void parseArguments(String[] args) { } private static X509TrustManager getTrustManager() throws Exception { + // generate certificate from cert string + CertificateFactory cf = CertificateFactory.getInstance("X.509"); // create a key store KeyStore ks = KeyStore.getInstance("JKS"); ks.load(null, null); - // generate certificate from cert string - Certificate trustedCert = pemDecoder.decode(trustedCertStr, X509Certificate.class); // import the trusted cert - ks.setCertificateEntry("RSA Export Signer", trustedCert); + try (ByteArrayInputStream is = + new ByteArrayInputStream(trustedCertStr.getBytes())) { + Certificate trustedCert = cf.generateCertificate(is); + ks.setCertificateEntry("RSA Export Signer", trustedCert); + } // create the trust manager TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmAlgorithm); @@ -271,11 +276,28 @@ private static X509TrustManager getTrustManager() throws Exception { private static X509Certificate[] getFraudulentChain() throws Exception { // generate certificate from cert string + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + X509Certificate[] chain = new X509Certificate[4]; - chain[0] = pemDecoder.decode(targetCertStr, X509Certificate.class); - chain[1] = pemDecoder.decode(intermediateCertStr, X509Certificate.class); - chain[2] = pemDecoder.decode(compromisedCertStr, X509Certificate.class); - chain[3] = pemDecoder.decode(untrustedCrossCertStr, X509Certificate.class); + try (ByteArrayInputStream is = + new ByteArrayInputStream(targetCertStr.getBytes())) { + chain[0] = (X509Certificate)cf.generateCertificate(is); + } + + try (ByteArrayInputStream is = + new ByteArrayInputStream(intermediateCertStr.getBytes())) { + chain[1] = (X509Certificate)cf.generateCertificate(is); + } + + try (ByteArrayInputStream is = + new ByteArrayInputStream(compromisedCertStr.getBytes())) { + chain[2] = (X509Certificate)cf.generateCertificate(is); + } + + try (ByteArrayInputStream is = + new ByteArrayInputStream(untrustedCrossCertStr.getBytes())) { + chain[3] = (X509Certificate)cf.generateCertificate(is); + } return chain; } diff --git a/test/jdk/sun/security/tools/jarsigner/EC.java b/test/jdk/sun/security/tools/jarsigner/EC.java index 1b41c48e2346d..848dc8bf843f9 100644 --- a/test/jdk/sun/security/tools/jarsigner/EC.java +++ b/test/jdk/sun/security/tools/jarsigner/EC.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 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 @@ -26,7 +26,6 @@ * @bug 6870812 * @summary enhance security tools to use ECC algorithm * @library /test/lib - * @run main/timeout=300 EC */ import jdk.test.lib.SecurityTools; diff --git a/test/jdk/sun/security/x509/AlgorithmId/AlgorithmIdEqualsHashCode.java b/test/jdk/sun/security/x509/AlgorithmId/AlgorithmIdEqualsHashCode.java index be3da70f85108..ff91e3dff81fe 100644 --- a/test/jdk/sun/security/x509/AlgorithmId/AlgorithmIdEqualsHashCode.java +++ b/test/jdk/sun/security/x509/AlgorithmId/AlgorithmIdEqualsHashCode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2021, 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 @@ -24,19 +24,16 @@ /* * @test * @author Gary Ellison - * @bug 4170635 8258247 8367008 - * @library /test/lib + * @bug 4170635 8258247 * @summary Verify equals()/hashCode() contract honored * @modules java.base/sun.security.x509 java.base/sun.security.util */ -import java.io.IOException; +import java.io.*; import java.security.AlgorithmParameters; import java.security.spec.MGF1ParameterSpec; import java.security.spec.PSSParameterSpec; -import jdk.test.lib.Asserts; - import sun.security.util.DerValue; import sun.security.x509.*; @@ -100,20 +97,5 @@ public static void main(String[] args) throws Exception { } else { System.out.println("PASSED equals() test"); } - - // Construct an AlgorithmId with explicit DER NULL parameters - DerValue explicitNullParams = new DerValue(DerValue.tag_Null, new byte[0]); - AlgorithmId aiNullParams = new AlgorithmId(AlgorithmId.SHA256_oid, - explicitNullParams); - // The constructor should canonicalize this to "no parameters" - Asserts.assertTrue(aiNullParams.getEncodedParams() == null); - AlgorithmId aiNormal = AlgorithmId.get("SHA-256"); - Asserts.assertEquals(aiNullParams, aiNormal); - Asserts.assertEquals(aiNullParams.hashCode(), aiNormal.hashCode()); - - // Test invalid ASN.1 NULL (non-zero length) - DerValue invalidNull = new DerValue(DerValue.tag_Null, new byte[]{0x00}); - Asserts.assertThrows(IOException.class, - () -> new AlgorithmId(AlgorithmId.SHA256_oid, invalidNull)); } } diff --git a/test/jdk/sun/security/x509/AlgorithmId/NullParams.java b/test/jdk/sun/security/x509/AlgorithmId/NullParams.java index 0b542997a1991..733ab9fa52231 100644 --- a/test/jdk/sun/security/x509/AlgorithmId/NullParams.java +++ b/test/jdk/sun/security/x509/AlgorithmId/NullParams.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 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 @@ -67,13 +67,6 @@ public static void main(String[] args) throws Exception { test("SHA3-256withRSA", true); test("SHA3-384withRSA", true); test("SHA3-512withRSA", true); - test("HmacSHA1", true); - test("HmacSHA224", true); - test("HmacSHA256", true); - test("HmacSHA384", true); - test("HmacSHA512", true); - test("HmacSHA512/224", true); - test("HmacSHA512/256", true); // Full old list: must be absent test("SHA1withECDSA", false); @@ -90,6 +83,7 @@ public static void main(String[] args) throws Exception { // Others test("DSA", false); test("SHA1withDSA", false); + test("HmacSHA1", false); if (failed) { throw new RuntimeException("At least one failed"); diff --git a/test/jdk/sun/security/x509/X509CRLImpl/Verify.java b/test/jdk/sun/security/x509/X509CRLImpl/Verify.java index a10a18971d20d..911f53f512075 100644 --- a/test/jdk/sun/security/x509/X509CRLImpl/Verify.java +++ b/test/jdk/sun/security/x509/X509CRLImpl/Verify.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,19 +25,11 @@ * @test * @bug 7026347 * @summary X509CRL should have verify(PublicKey key, Provider sigProvider) - * @enablePreview */ -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.security.PEMDecoder; -import java.security.Provider; -import java.security.PublicKey; -import java.security.Security; -import java.security.SignatureException; -import java.security.cert.CRLException; -import java.security.cert.X509CRL; -import java.security.cert.X509Certificate; +import java.io.ByteArrayInputStream; +import java.security.*; +import java.security.cert.*; public class Verify { @@ -152,21 +144,23 @@ public static void main(String[] args) throws Exception { } } - private static void setup() { + private static void setup() throws CertificateException, CRLException { + CertificateFactory cf = CertificateFactory.getInstance("X.509"); - final PEMDecoder pemDecoder = PEMDecoder.of(); /* Create CRL */ - crl = pemDecoder.decode(crlStr, X509CRL.class); + ByteArrayInputStream inputStream = + new ByteArrayInputStream(crlStr.getBytes()); + crl = (X509CRL)cf.generateCRL(inputStream); /* Get public key of the CRL issuer cert */ - crlIssuerCertPubKey = pemDecoder.decode(crlIssuerCertStr, X509Certificate.class) - .getPublicKey(); - + inputStream = new ByteArrayInputStream(crlIssuerCertStr.getBytes()); + X509Certificate cert + = (X509Certificate)cf.generateCertificate(inputStream); + crlIssuerCertPubKey = cert.getPublicKey(); /* Get public key of the self-signed Cert */ - selfSignedCertPubKey = pemDecoder.decode(selfSignedCertStr, X509Certificate.class) - .getPublicKey(); - + inputStream = new ByteArrayInputStream(selfSignedCertStr.getBytes()); + selfSignedCertPubKey = cf.generateCertificate(inputStream).getPublicKey(); } private static void verifyCRL(PublicKey key, String providerName) diff --git a/test/jdk/tools/jpackage/apps/PrintEnv.java b/test/jdk/tools/jpackage/apps/PrintEnv.java index 4aed3c4142257..64a243a0abcfa 100644 --- a/test/jdk/tools/jpackage/apps/PrintEnv.java +++ b/test/jdk/tools/jpackage/apps/PrintEnv.java @@ -69,7 +69,6 @@ private static List printArgs(String[] args) { lines.add(ModuleFinder.ofSystem().findAll().stream() .map(ModuleReference::descriptor) .map(ModuleDescriptor::name) - .sorted() .collect(Collectors.joining(","))); } else if (arg.equals(PRINT_WORK_DIR)) { lines.add("$CD=" + Path.of("").toAbsolutePath()); diff --git a/test/jdk/tools/jpackage/clean_stashed_files.sh b/test/jdk/tools/jpackage/clean_stashed_files.sh index db393877b1989..28ad42048acff 100644 --- a/test/jdk/tools/jpackage/clean_stashed_files.sh +++ b/test/jdk/tools/jpackage/clean_stashed_files.sh @@ -120,7 +120,8 @@ macDmgFilterScpt() { # - Trim random absolute temp path # - Replace "/dmg-workdir/" (new) with "/images/" (old) find "$stash_dir" -name '*.scpt' -type f | xargs -I {} sed $sed_inplace_option \ - -e 's|/jdk.jpackage[0-9]\{1,\}/|/jdk.jpackage/|' \ + -e 's|"/.*/jdk.jpackage[0-9]\{1,\}/|"/jdk.jpackage/|' \ + -e 's|"file:///.*/jdk.jpackage[0-9]\{1,\}/|"file:///jdk.jpackage/|' \ -e 's|/dmg-workdir/|/images/|' \ '{}' } diff --git a/test/jdk/tools/jpackage/clean_test_output.sh b/test/jdk/tools/jpackage/clean_test_output.sh index 200d6add299d0..e472d780dede7 100644 --- a/test/jdk/tools/jpackage/clean_test_output.sh +++ b/test/jdk/tools/jpackage/clean_test_output.sh @@ -56,9 +56,6 @@ filterFile () { # Strip variable part of temporary directory name `jdk.jpackage5060841750457404688` -e 's|\([\/]\)jdk\.jpackage[0-9]\{1,\}\b|\1jdk.jpackage|g' - # Strip variable part of temporary directory name `jdk.jpackage.test217379316521032539` - -e 's|\([\/]\)jdk\.jpackage\.test[0-9]\{1,\}\b|\1jdk.jpackage.test|g' - # Convert PID value `[PID: 131561]` -e 's/\[PID: [0-9]\{1,\}\]/[PID: ]/' @@ -79,41 +76,6 @@ filterFile () { # Convert variable part of stack trace entry `at jdk.jpackage.test.JPackageCommand.execute(JPackageCommand.java:863)` -e 's/^\(.*\b\.java:\)[0-9]\{1,\}\()\r\{0,1\}\)$/\1N\2/' - - # Whipe out entire output of /usr/bin/hdiutil command. - # It is of little to no interest and contains too many variable parts to deal with individually. - -e '/^Running \/usr\/bin\/hdiutil/,/^Returned:/{ - //,/^Output:/!d - }' - - # Zip stack traces. - -e $'/^\tat /{ - :a - g - N - s/.*\\n// - /^\tat /ba - s/\\(^\t... \\)[0-9]\\{1,\\}\\( more\\)/\\1N\\2/ - s/\(.*\)/\tat \\n\\1/ - P - D - }' - - # Convert PID value in `taskkill /F /PID 5640` - -e 's|taskkill /F /PID [0-9]\{1,\}|taskkill /F /PID |' - - # Convert PID value in `The process with PID 5640 has been terminated` - -e 's|\(The process with PID \)[0-9]\{1,\}\( has been terminated\)|\1\2|' - - # Convert timeout value in `Check timeout value 57182ms is positive` - -e 's|\(Check timeout value \)[0-9]\{1,\}\(ms is positive\)|\1\2|' - - # Convert variable part of /usr/bin/osascript output `jdk.jpackage/config/SigningRuntimeImagePackageTest-dmg-setup.scpt:455:497: execution error: Finder got an error: Can’t set 1 to icon view. (-10006)` - -e 's|\(-dmg-setup.scpt:\)[0-9]\{1,\}:[0-9]\{1,\}\(: execution error: \)|\1\2|' - - # Use the same name for all exceptions. - -e 's|[^ ]\{1,\}\.[^ ]\{1,\}\Exception:|:|g' - -e 's|[^ ]\{1,\}\.[^ ]\{1,\}\ExceptionBox:|:|g' ) sed $sed_inplace_option "$1" "${expressions[@]}" diff --git a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/AnnotationsTest.java b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/AnnotationsTest.java index f88d1f81a3467..e16b175ab8a0c 100644 --- a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/AnnotationsTest.java +++ b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/AnnotationsTest.java @@ -95,18 +95,6 @@ public void testVarArg2(int a, String b, String ... other) { recordTestCase(a, b, other); } - enum Tack { - STARBOARD, - PORTSIDE; - } - - @Test - @Parameter({"STARBOARD"}) - @Parameter({"PORTSIDE", "STARBOARD"}) - public void testEnumVarArg(Tack ... cource) { - recordTestCase((Object[]) cource); - } - @Test @ParameterSupplier("dateSupplier") @ParameterSupplier("jdk.jpackage.test.AnnotationsTest.dateSupplier") @@ -130,8 +118,6 @@ public static Set getExpectedTestDescs() { "().testVarArg2(-89, bar, [more, moore](length=2))", "().testVarArg2(-89, bar, [more](length=1))", "().testVarArg2(12, foo, [](length=0))", - "().testEnumVarArg(STARBOARD)", - "().testEnumVarArg(PORTSIDE, STARBOARD)", "().testDates(2018-05-05)", "().testDates(2018-07-11)", "().testDates(2034-05-05)", diff --git a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/JUnitUtilsTest.java b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/JUnitUtilsTest.java deleted file mode 100644 index 28b55f98fe203..0000000000000 --- a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/JUnitUtilsTest.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * 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 jdk.jpackage.test; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; - -import java.util.Map; -import org.junit.jupiter.api.Test; - -public class JUnitUtilsTest { - - @Test - public void test_assertArrayEquals() { - JUnitUtils.assertArrayEquals(new int[] {1, 2, 3}, new int[] {1, 2, 3}); - JUnitUtils.assertArrayEquals(new long[] {1, 2, 3}, new long[] {1, 2, 3}); - JUnitUtils.assertArrayEquals(new boolean[] {true, true}, new boolean[] {true, true}); - } - - @Test - public void test_assertArrayEquals_negative() { - assertThrows(AssertionError.class, () -> { - JUnitUtils.assertArrayEquals(new int[] {1, 2, 3}, new int[] {2, 3}); - }); - } - - @Test - public void test_exceptionAsPropertyMapWithMessageWithoutCause() { - - var ex = new Exception("foo"); - - var map = JUnitUtils.exceptionAsPropertyMap(ex); - - assertEquals(Map.of("getClass", Exception.class.getName(), "getMessage", "foo"), map); - } -} diff --git a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/ObjectMapperTest.java b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/ObjectMapperTest.java deleted file mode 100644 index 0310d276e218b..0000000000000 --- a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/ObjectMapperTest.java +++ /dev/null @@ -1,731 +0,0 @@ -/* - * 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 jdk.jpackage.test; - -import static org.junit.jupiter.api.Assertions.assertArrayEquals; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.junit.jupiter.api.Assertions.assertNull; -import static org.junit.jupiter.api.Assertions.assertSame; -import static org.junit.jupiter.api.Assertions.assertThrowsExactly; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.math.BigInteger; -import java.nio.file.Path; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.UUID; -import java.util.function.BiConsumer; -import java.util.function.BiFunction; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.Predicate; -import java.util.function.Supplier; -import org.junit.jupiter.api.Test; - -public class ObjectMapperTest { - - @Test - public void test_String() { - var om = ObjectMapper.blank().create(); - - var map = om.map("foo"); - - assertEquals("foo", map); - } - - @Test - public void test_int() { - var om = ObjectMapper.blank().create(); - - var map = om.map(100); - - assertEquals(100, map); - } - - @Test - public void test_null() { - var om = ObjectMapper.blank().create(); - - var map = om.map(null); - - assertNull(map); - } - - @Test - public void test_Object() { - var obj = new Object(); - assertSame(obj, ObjectMapper.blank().create().map(obj)); - assertSame(obj, ObjectMapper.standard().create().map(obj)); - } - - @Test - public void test_Path() { - var obj = Path.of("foo/bar"); - - assertSame(obj, ObjectMapper.standard().create().map(obj)); - } - - @Test - public void test_UUID() { - var obj = UUID.randomUUID(); - - assertSame(obj, ObjectMapper.standard().create().map(obj)); - } - - @Test - public void test_BigInteger() { - var obj = BigInteger.TEN; - - assertSame(obj, ObjectMapper.standard().create().map(obj)); - } - - @Test - public void test_Enum() { - - var expected = Map.of( - "name", TestEnum.BAR.name(), - "ordinal", TestEnum.BAR.ordinal(), - "a", "A", - "b", 123, - "num", 100 - ); - - assertEquals(expected, ObjectMapper.standard().create().map(TestEnum.BAR)); - } - - @Test - public void test_array_int() { - - var obj = new int[] { 1, 4, 5 }; - - assertSame(obj, ObjectMapper.standard().create().map(obj)); - } - - @Test - public void test_array_String() { - - var obj = new String[] { "Hello", "Bye" }; - - assertSame(obj, ObjectMapper.standard().create().map(obj)); - } - - @Test - public void test_array_empty() { - - var obj = new Thread[0]; - - assertSame(obj, ObjectMapper.standard().create().map(obj)); - } - - @Test - public void test_array_nulls() { - - var obj = new Thread[10]; - - assertSame(obj, ObjectMapper.standard().create().map(obj)); - } - - @Test - public void test_array_Path() { - - var obj = new Path[] { Path.of("foo/bar"), null, Path.of("").toAbsolutePath() }; - - assertSame(obj, ObjectMapper.standard().create().map(obj)); - } - - @Test - public void test_array_Object() { - - var obj = new Object[] { Path.of("foo/bar"), null, 145, new Simple.Stub("Hello", 738), "foo" }; - - var expected = new Object[] { Path.of("foo/bar"), null, 145, Map.of("a", "Hello", "b", 738), "foo" }; - - assertArrayEquals(expected, (Object[])ObjectMapper.standard().create().map(obj)); - } - - @Test - public void test_functional() { - assertWrappedIdentity(new Function() { - - @Override - public Integer apply(Object o) { - throw new AssertionError(); - } - - }); - - assertWrappedIdentity(new BiFunction() { - - @Override - public Integer apply(Object a, String b) { - throw new AssertionError(); - } - - }); - - assertWrappedIdentity(new Consumer<>() { - - @Override - public void accept(Object o) { - throw new AssertionError(); - } - - }); - - assertWrappedIdentity(new BiConsumer<>() { - - @Override - public void accept(Object a, Object b) { - throw new AssertionError(); - } - - }); - - assertWrappedIdentity(new Predicate<>() { - - @Override - public boolean test(Object o) { - throw new AssertionError(); - } - - }); - - assertWrappedIdentity(new Supplier<>() { - - @Override - public Object get() { - throw new AssertionError(); - } - - }); - - assertWrappedIdentity(new Runnable() { - - @Override - public void run() { - throw new AssertionError(); - } - - }); - } - - @Test - public void testIdentityWrapper() { - var om = ObjectMapper.standard().create(); - - var a = new Object() {}; - var b = new Object() {}; - - var amap = om.map(a); - var amap2 = om.map(a); - - assertEquals(amap, amap2); - assertEquals(ObjectMapper.wrapIdentity(a), amap); - - var bmap = om.map(b); - - assertNotEquals(amap, bmap); - assertEquals(ObjectMapper.wrapIdentity(b), bmap); - } - - @Test - public void test_wrapIdentity() { - - assertThrowsExactly(NullPointerException.class, () -> ObjectMapper.wrapIdentity(null)); - - var iw = ObjectMapper.wrapIdentity(new Object()); - - assertSame(iw, ObjectMapper.wrapIdentity(iw)); - - var simpleStubA = new Simple.Stub("Hello", 77); - var simpleStubB = new Simple.Stub("Hello", 77); - - assertEquals(simpleStubA, simpleStubB); - assertNotEquals(ObjectMapper.wrapIdentity(simpleStubA), ObjectMapper.wrapIdentity(simpleStubB)); - assertEquals(ObjectMapper.wrapIdentity(simpleStubA), ObjectMapper.wrapIdentity(simpleStubA)); - } - - @Test - public void test_empty_List() { - var om = ObjectMapper.blank().create(); - - var map = om.map(List.of()); - - assertEquals(List.of(), map); - } - - @Test - public void test_List() { - var om = ObjectMapper.blank().create(); - - var map = om.map(List.of(100, "foo")); - - assertEquals(List.of(100, "foo"), map); - } - - @Test - public void test_empty_Map() { - var om = ObjectMapper.blank().create(); - - var map = om.map(Map.of()); - - assertEquals(Map.of(), map); - } - - @Test - public void test_Map() { - var om = ObjectMapper.blank().create(); - - var map = om.map(Map.of(100, "foo")); - - assertEquals(Map.of(100, "foo"), map); - } - - @Test - public void test_MapSimple() { - var om = ObjectMapper.standard().create(); - - var map = om.map(Map.of(123, "foo", 321, new Simple.Stub("Hello", 567))); - - assertEquals(Map.of(123, "foo", 321, Map.of("a", "Hello", "b", 567)), map); - } - - @Test - public void test_ListSimple() { - var om = ObjectMapper.standard().create(); - - var map = om.map(List.of(100, new Simple.Stub("Hello", 567), "bar", new Simple() {})); - - assertEquals(List.of(100, Map.of("a", "Hello", "b", 567), "bar", Map.of("a", "foo", "b", 123)), map); - } - - @Test - public void test_Simple() { - var om = ObjectMapper.standard().create(); - - var map = om.map(new Simple() {}); - - assertEquals(Map.of("a", "foo", "b", 123), map); - } - - @Test - public void test_Proxy() { - var om = ObjectMapper.standard().create(); - - var map = om.map(Proxy.newProxyInstance(Simple.class.getClassLoader(), new Class[] { Simple.class }, new InvocationHandler() { - - @Override - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - switch (method.getName()) { - case "a" -> { - return "Bye"; - } - case "b" -> { - return 335; - } - default -> { - throw new UnsupportedOperationException(); - } - } - } - - })); - - assertEquals(Map.of("a", "Bye", "b", 335), map); - } - - @Test - public void test_Simple_null_property() { - var om = ObjectMapper.standard().create(); - - var map = om.map(new Simple.Stub(null, 123)); - - assertEquals(Map.of("b", 123, "a", ObjectMapper.NULL), map); - } - - @Test - public void test_Optional_String() { - var om = ObjectMapper.standard().create(); - - var map = om.map(Optional.of("foo")); - - assertEquals(Map.of("get", "foo"), map); - } - - @Test - public void test_Optional_empty() { - var om = ObjectMapper.standard().create(); - - var map = om.map(Optional.empty()); - - assertEquals(Map.of("get", ObjectMapper.NULL), map); - } - - @Test - public void test_toMap() { - var om = ObjectMapper.standard().create(); - - assertNull(om.toMap(null)); - assertEquals(Map.of("value", "Hello"), om.toMap("Hello")); - assertEquals(Map.of("a", "foo", "b", 123), om.toMap(new Simple() {})); - } - - @Test - public void test_getter_throws() { - var om = ObjectMapper.blank() - .mutate(ObjectMapper.configureObject()) - .mutate(ObjectMapper.configureLeafClasses()) - .mutate(ObjectMapper.configureException()) - .create(); - - var expected = Map.of("get", om.toMap(new UnsupportedOperationException("Not for you!"))); - - var actual = om.toMap(new Supplier<>() { - @Override - public Object get() { - throw new UnsupportedOperationException("Not for you!"); - } - }); - - assertEquals(expected, actual); - } - - @Test - public void test_exception_with_message_with_cause() { - - var ex = new Exception("foo", new IllegalArgumentException("Cause", new RuntimeException("Ops!"))); - - var om = ObjectMapper.standard().create(); - - var map = om.toMap(ex); - - assertEquals(Map.of( - "getClass", Exception.class.getName(), - "getMessage", "foo", - "getCause", Map.of( - "getClass", IllegalArgumentException.class.getName(), - "getMessage", "Cause", - "getCause", Map.of( - "getClass", RuntimeException.class.getName(), - "getMessage", "Ops!" - ) - ) - ), map); - } - - @Test - public void test_exception_without_message_with_cause() { - - var ex = new RuntimeException(null, new UnknownError("Ops!")); - - var om = ObjectMapper.standard().create(); - - var map = om.toMap(ex); - - assertEquals(Map.of( - "getClass", RuntimeException.class.getName(), - "getCause", Map.of( - "getMessage", "Ops!", - "getCause", ObjectMapper.NULL - ) - ), map); - } - - @Test - public void test_exception_without_message_without_cause() { - - var ex = new UnsupportedOperationException(); - - var om = ObjectMapper.standard().create(); - - var map = om.toMap(ex); - - assertEquals(Map.of("getClass", UnsupportedOperationException.class.getName()), map); - } - - @Test - public void test_exception_CustomException() { - - var ex = new CustomException("Hello", Path.of(""), Optional.empty(), null); - - var om = ObjectMapper.standard().create(); - - var map = om.toMap(ex); - - assertEquals(Map.of( - "getClass", CustomException.class.getName(), - "getMessage", "Hello", - "op", Map.of("get", ObjectMapper.NULL), - "path2", Path.of("") - ), map); - } - - @Test - public void test_Builder_accessPackageMethods() { - - var obj = new TestType().foo("Hello").bar(81); - - var map = ObjectMapper.standard().create().toMap(obj); - - assertEquals(Map.of("foo", "Hello"), map); - - map = ObjectMapper.standard().accessPackageMethods(TestType.class.getPackage()).create().toMap(obj); - - assertEquals(Map.of("foo", "Hello", "bar", 81), map); - } - - @Test - public void test_Builder_methods_Simple() { - - var om = ObjectMapper.standard().exceptSomeMethods(Simple.class).add("a").apply().create(); - - assertEquals(Map.of("b", 123), om.toMap(new Simple() {})); - assertEquals(Map.of("b", 345), om.toMap(new Simple.Stub("Hello", 345))); - assertEquals(Map.of("b", 123), om.toMap(new Simple.Default("Hello"))); - assertEquals(Map.of("b", 345 + 10), om.toMap(new Simple.DefaultExt("Hello", 345))); - - om = ObjectMapper.standard().exceptSomeMethods(Simple.class).add("b").apply().create(); - - assertEquals(Map.of("a", "foo"), om.toMap(new Simple() {})); - assertEquals(Map.of("a", "Hello"), om.toMap(new Simple.Stub("Hello", 345))); - assertEquals(Map.of("a", "Hello"), om.toMap(new Simple.Default("Hello"))); - assertEquals(Map.of("a", "[Hello]"), om.toMap(new Simple.DefaultExt("Hello", 345))); - } - - @Test - public void test_Builder_methods_SimpleStub() { - - var om = ObjectMapper.standard().exceptSomeMethods(Simple.Stub.class).add("a").apply().create(); - - assertEquals(Map.of("a", "foo", "b", 123), om.toMap(new Simple() {})); - assertEquals(Map.of("b", 345), om.toMap(new Simple.Stub("Hello", 345))); - assertEquals(Map.of("a", "Hello", "b", 123), om.toMap(new Simple.Default("Hello"))); - assertEquals(Map.of("a", "[Hello]", "b", 345 + 10), om.toMap(new Simple.DefaultExt("Hello", 345))); - - om = ObjectMapper.standard().exceptSomeMethods(Simple.Stub.class).add("b").apply().create(); - - assertEquals(Map.of("a", "foo", "b", 123), om.toMap(new Simple() {})); - assertEquals(Map.of("a", "Hello"), om.toMap(new Simple.Stub("Hello", 345))); - assertEquals(Map.of("a", "Hello", "b", 123), om.toMap(new Simple.Default("Hello"))); - assertEquals(Map.of("a", "[Hello]", "b", 345 + 10), om.toMap(new Simple.DefaultExt("Hello", 345))); - } - - @Test - public void test_Builder_methods_SimpleDefault() { - - var om = ObjectMapper.standard().exceptSomeMethods(Simple.Default.class).add("a").apply().create(); - - assertEquals(Map.of("a", "foo", "b", 123), om.toMap(new Simple() {})); - assertEquals(Map.of("a", "Hello", "b", 345), om.toMap(new Simple.Stub("Hello", 345))); - assertEquals(Map.of("b", 123), om.toMap(new Simple.Default("Hello"))); - assertEquals(Map.of("b", 345 + 10), om.toMap(new Simple.DefaultExt("Hello", 345))); - - om = ObjectMapper.standard().exceptSomeMethods(Simple.Default.class).add("b").apply().create(); - - assertEquals(Map.of("a", "foo"), om.toMap(new Simple() {})); - assertEquals(Map.of("a", "Hello"), om.toMap(new Simple.Stub("Hello", 345))); - assertEquals(Map.of("a", "Hello"), om.toMap(new Simple.Default("Hello"))); - assertEquals(Map.of("a", "[Hello]"), om.toMap(new Simple.DefaultExt("Hello", 345))); - } - - @Test - public void test_Builder_methods_SimpleDefaultExt() { - - var om = ObjectMapper.standard().exceptSomeMethods(Simple.DefaultExt.class).add("a").apply().create(); - - assertEquals(Map.of("a", "foo", "b", 123), om.toMap(new Simple() {})); - assertEquals(Map.of("a", "Hello", "b", 345), om.toMap(new Simple.Stub("Hello", 345))); - assertEquals(Map.of("a", "Hello", "b", 123), om.toMap(new Simple.Default("Hello"))); - assertEquals(Map.of("b", 345 + 10), om.toMap(new Simple.DefaultExt("Hello", 345))); - - om = ObjectMapper.standard().exceptSomeMethods(Simple.DefaultExt.class).add("b").apply().create(); - - assertEquals(Map.of("a", "foo", "b", 123), om.toMap(new Simple() {})); - assertEquals(Map.of("a", "Hello", "b", 345), om.toMap(new Simple.Stub("Hello", 345))); - assertEquals(Map.of("a", "Hello", "b", 123), om.toMap(new Simple.Default("Hello"))); - assertEquals(Map.of("a", "[Hello]"), om.toMap(new Simple.DefaultExt("Hello", 345))); - } - - @Test - public void test_Builder_methods_SimpleStub_and_SimpleDefault() { - - var om = ObjectMapper.standard() - .exceptSomeMethods(Simple.Stub.class).add("a").apply() - .exceptSomeMethods(Simple.Default.class).add("a").apply() - .create(); - - assertEquals(Map.of("a", "foo", "b", 123), om.toMap(new Simple() {})); - assertEquals(Map.of("b", 345), om.toMap(new Simple.Stub("Hello", 345))); - assertEquals(Map.of("b", 123), om.toMap(new Simple.Default("Hello"))); - assertEquals(Map.of("b", 345 + 10), om.toMap(new Simple.DefaultExt("Hello", 345))); - - om = ObjectMapper.standard() - .exceptSomeMethods(Simple.Stub.class).add("b").apply() - .exceptSomeMethods(Simple.Default.class).add("b").apply() - .create(); - - assertEquals(Map.of("a", "foo"), om.toMap(new Simple() {})); - assertEquals(Map.of("a", "Hello"), om.toMap(new Simple.Stub("Hello", 345))); - assertEquals(Map.of("a", "Hello"), om.toMap(new Simple.Default("Hello"))); - assertEquals(Map.of("a", "[Hello]"), om.toMap(new Simple.DefaultExt("Hello", 345))); - } - - @Test - public void test_Builder_methods_all_excluded() { - - var om = ObjectMapper.standard() - .exceptSomeMethods(Simple.class).add("a").apply() - .exceptSomeMethods(Simple.Stub.class).add("b").apply() - .create(); - - var obj = new Simple.Stub("Hello", 345); - - assertEquals(ObjectMapper.wrapIdentity(obj), om.map(obj)); - } - - interface Simple { - default String a() { - return "foo"; - } - - default int b() { - return 123; - } - - record Stub(String a, int b) implements Simple {} - - static class Default implements Simple { - Default(String a) { - this.a = a; - } - - @Override - public String a() { - return a; - } - - private final String a; - } - - static class DefaultExt extends Default { - DefaultExt(String a, int b) { - super(a); - this.b = b; - } - - @Override - public String a() { - return "[" + super.a() + "]"; - } - - @Override - public int b() { - return 10 + b; - } - - private final int b; - } - } - - final class TestType { - - public String foo() { - return foo; - } - - public TestType foo(String v) { - foo = v; - return this; - } - - int bar() { - return bar; - } - - TestType bar(int v) { - bar = v; - return this; - } - - private String foo; - private int bar; - } - - enum TestEnum implements Simple { - FOO, - BAR; - - public int num() { - return 100; - } - - public int num(int v) { - return v; - } - - @Override - public String a() { - return "A"; - } - } - - static final class CustomException extends Exception { - - CustomException(String message, Path path, Optional optional, Throwable cause) { - super(message, cause); - this.path = path; - this.optional = optional; - } - - Path path() { - return path; - } - - public Path path2() { - return path; - } - - public Optional op() { - return optional; - } - - private final Path path; - private final Optional optional; - - private static final long serialVersionUID = 1L; - - } - - private static void assertWrappedIdentity(ObjectMapper om, Object obj) { - var map = om.toMap(obj); - assertEquals(Map.of("value", ObjectMapper.wrapIdentity(obj)), map); - } - - private static void assertWrappedIdentity(Object obj) { - assertWrappedIdentity(ObjectMapper.standard().create(), obj); - } -} diff --git a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/PackageTestTest.java b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/PackageTestTest.java index 4cf89fca3cc8a..da94db30925da 100644 --- a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/PackageTestTest.java +++ b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/PackageTestTest.java @@ -341,7 +341,7 @@ public PackageType packageType() { } @Override - JPackageCommand runStandardAsserts() { + JPackageCommand assertAppLayout() { return this; } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/AdditionalLauncher.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/AdditionalLauncher.java index 66da89fc3f98a..50222d89cebdc 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/AdditionalLauncher.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/AdditionalLauncher.java @@ -198,7 +198,7 @@ static void forEachAdditionalLauncher(JPackageCommand cmd, } } - public static PropertyFile getAdditionalLauncherProperties( + static PropertyFile getAdditionalLauncherProperties( JPackageCommand cmd, String launcherName) { PropertyFile shell[] = new PropertyFile[1]; forEachAdditionalLauncher(cmd, (name, propertiesFilePath) -> { diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/ApplicationLayout.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/ApplicationLayout.java index 0701421e999f8..7ab3b824aa44b 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/ApplicationLayout.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/ApplicationLayout.java @@ -98,18 +98,12 @@ public static ApplicationLayout platformAppImage() { throw new IllegalArgumentException("Unknown platform"); } - public static ApplicationLayout platformJavaRuntime() { - Path runtime = Path.of(""); - Path runtimeHome = runtime; - if (TKit.isOSX()) { - runtimeHome = Path.of("Contents/Home"); - } - + public static ApplicationLayout javaRuntime() { return new ApplicationLayout( null, null, - runtime, - runtimeHome, + Path.of(""), + null, null, null, null, diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/ConfigFilesStasher.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/ConfigFilesStasher.java index 2321e4e852e3e..e630659bdb17d 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/ConfigFilesStasher.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/ConfigFilesStasher.java @@ -374,14 +374,8 @@ private boolean isPathEmpty() { private static Path setupDirectory(JPackageCommand cmd, String argName) { if (!cmd.hasArgument(argName)) { - // Use absolute path as jpackage can be executed in another directory. - // Some tests expect a specific last argument, don't interfere with them - // and insert the argument at the beginning of the command line. - List args = new ArrayList<>(); - args.add(argName); - args.add(TKit.createTempDirectory("stash-script-resource-dir").toAbsolutePath().toString()); - args.addAll(cmd.getAllArguments()); - cmd.clearArguments().addArguments(args); + // Use absolute path as jpackage can be executed in another directory + cmd.setArgumentValue(argName, TKit.createTempDirectory("stash-script-resource-dir").toAbsolutePath()); } return Path.of(cmd.getArgumentValue(argName)); diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/ConfigurationTarget.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/ConfigurationTarget.java deleted file mode 100644 index 0d68d055b921e..0000000000000 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/ConfigurationTarget.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * 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 jdk.jpackage.test; - -import java.util.Objects; -import java.util.Optional; -import java.util.function.Consumer; - -/** - * Provides uniform way to configure {@code JPackageCommand} and - * {@code PackageTest} instances. - */ -public record ConfigurationTarget(Optional cmd, Optional test) { - - public ConfigurationTarget { - Objects.requireNonNull(cmd); - Objects.requireNonNull(test); - if (cmd.isEmpty() == test.isEmpty()) { - throw new IllegalArgumentException(); - } - } - - public ConfigurationTarget(JPackageCommand target) { - this(Optional.of(target), Optional.empty()); - } - - public ConfigurationTarget(PackageTest target) { - this(Optional.empty(), Optional.of(target)); - } - - public ConfigurationTarget apply(Consumer a, Consumer b) { - cmd.ifPresent(Objects.requireNonNull(a)); - test.ifPresent(Objects.requireNonNull(b)); - return this; - } - - public ConfigurationTarget addInitializer(Consumer initializer) { - cmd.ifPresent(Objects.requireNonNull(initializer)); - test.ifPresent(v -> { - v.addInitializer(initializer::accept); - }); - return this; - } - - public ConfigurationTarget addInstallVerifier(Consumer verifier) { - cmd.ifPresent(Objects.requireNonNull(verifier)); - test.ifPresent(v -> { - v.addInstallVerifier(verifier::accept); - }); - return this; - } - - public ConfigurationTarget addRunOnceInitializer(Consumer initializer) { - Objects.requireNonNull(initializer); - cmd.ifPresent(_ -> { - initializer.accept(this); - }); - test.ifPresent(v -> { - v.addRunOnceInitializer(() -> { - initializer.accept(this); - }); - }); - return this; - } - - public ConfigurationTarget add(AdditionalLauncher addLauncher) { - return apply(addLauncher::applyTo, addLauncher::applyTo); - } -} diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/FileAssociations.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/FileAssociations.java index 576e294874af8..ebdbb4740066c 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/FileAssociations.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/FileAssociations.java @@ -27,11 +27,12 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; -import java.util.TreeMap; +import java.util.stream.Stream; import jdk.jpackage.internal.util.PathUtils; @@ -43,7 +44,7 @@ public FileAssociations(String faSuffixName) { } private void createFile() { - Map entries = new TreeMap<>(Map.of( + Map entries = new HashMap<>(Map.of( "extension", suffixName, "mime-type", getMime() )); diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/HelloApp.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/HelloApp.java index 6c7b6a2525570..69ea4ecfaa099 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/HelloApp.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/HelloApp.java @@ -125,8 +125,6 @@ private JarBuilder createJarBuilder() { if (appDesc.isWithMainClass()) { builder.setMainClass(appDesc.className()); } - // Use an old release number to make test app classes runnable on older runtimes. - builder.setRelease(11); return builder; } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java index b3729093ad200..8984450f54be2 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java @@ -39,6 +39,7 @@ import java.security.SecureRandom; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.ListIterator; @@ -67,11 +68,9 @@ */ public class JPackageCommand extends CommandArguments { - @SuppressWarnings("this-escape") public JPackageCommand() { prerequisiteActions = new Actions(); verifyActions = new Actions(); - excludeStandardAsserts(StandardAssert.MAIN_LAUNCHER_DESCRIPTION); } private JPackageCommand(JPackageCommand cmd, boolean immutable) { @@ -87,7 +86,7 @@ private JPackageCommand(JPackageCommand cmd, boolean immutable) { dmgInstallDir = cmd.dmgInstallDir; prerequisiteActions = new Actions(cmd.prerequisiteActions); verifyActions = new Actions(cmd.verifyActions); - standardAsserts = cmd.standardAsserts; + appLayoutAsserts = cmd.appLayoutAsserts; readOnlyPathAsserts = cmd.readOnlyPathAsserts; outputValidators = cmd.outputValidators; executeInDirectory = cmd.executeInDirectory; @@ -203,17 +202,6 @@ public JPackageCommand addArguments(String name, Path value) { return addArguments(name, value.toString()); } - public JPackageCommand mutate(Consumer mutator) { - return mutate(List.of(mutator)); - } - - public JPackageCommand mutate(Iterable> mutators) { - for (var mutator : mutators) { - mutator.accept(this); - } - return this; - } - public boolean isImagePackageType() { return PackageType.IMAGE == getArgumentValue("--type", () -> null, PACKAGE_TYPES::get); @@ -472,7 +460,7 @@ public ApplicationLayout appLayout() { if (layout != null) { } else if (isRuntime()) { - layout = ApplicationLayout.platformJavaRuntime(); + layout = ApplicationLayout.javaRuntime(); } else { layout = ApplicationLayout.platformAppImage(); } @@ -703,7 +691,7 @@ public boolean isPackageUnpacked() { } public static void useToolProviderByDefault(ToolProvider jpackageToolProvider) { - defaultToolProvider.set(Optional.of(jpackageToolProvider)); + defaultToolProvider = Optional.of(jpackageToolProvider); } public static void useToolProviderByDefault() { @@ -711,7 +699,7 @@ public static void useToolProviderByDefault() { } public static void useExecutableByDefault() { - defaultToolProvider.set(Optional.empty()); + defaultToolProvider = Optional.empty(); } public JPackageCommand useToolProvider(boolean v) { @@ -820,9 +808,7 @@ public JPackageCommand validateOutput(CannedFormattedString... str) { } public boolean isWithToolProvider() { - return Optional.ofNullable(withToolProvider).orElseGet(() -> { - return defaultToolProvider.get().isPresent(); - }); + return Optional.ofNullable(withToolProvider).orElseGet(defaultToolProvider::isPresent); } public JPackageCommand executePrerequisiteActions() { @@ -838,7 +824,7 @@ private Executor createExecutor() { .addArguments(args); if (isWithToolProvider()) { - exec.setToolProvider(defaultToolProvider.get().orElseGet(JavaTool.JPACKAGE::asToolProvider)); + exec.setToolProvider(defaultToolProvider.orElseGet(JavaTool.JPACKAGE::asToolProvider)); } else { exec.setExecutable(JavaTool.JPACKAGE); if (TKit.isWindows()) { @@ -946,7 +932,7 @@ public Executor.Result executeAndAssertImageCreated() { public JPackageCommand assertImageCreated() { verifyIsOfType(PackageType.IMAGE); - runStandardAsserts(); + assertAppLayout(); return this; } @@ -989,10 +975,10 @@ private static final class ReadOnlyPathsAssert { void updateAndAssert() { final var newSnapshots = createSnapshots(); for (final var a : asserts.keySet().stream().sorted().toList()) { - final var snapshotGroup = snapshots.get(a); - final var newSnapshotGroup = newSnapshots.get(a); - for (int i = 0; i < snapshotGroup.size(); i++) { - snapshotGroup.get(i).assertEquals(newSnapshotGroup.get(i), + final var snapshopGroup = snapshots.get(a); + final var newSnapshopGroup = newSnapshots.get(a); + for (int i = 0; i < snapshopGroup.size(); i++) { + TKit.PathSnapshot.assertEquals(snapshopGroup.get(i), newSnapshopGroup.get(i), String.format("Check jpackage didn't modify ${%s}=[%s]", a, asserts.get(a).get(i))); } } @@ -1107,7 +1093,7 @@ public JPackageCommand excludeReadOnlyPathAssert(ReadOnlyPathAssert... asserts) asSet::contains)).toArray(ReadOnlyPathAssert[]::new)); } - public static enum StandardAssert { + public static enum AppLayoutAssert { APP_IMAGE_FILE(JPackageCommand::assertAppImageFile), PACKAGE_FILE(JPackageCommand::assertPackageFile), NO_MAIN_LAUNCHER_IN_RUNTIME(cmd -> { @@ -1127,11 +1113,6 @@ public static enum StandardAssert { LauncherVerifier.Action.VERIFY_MAC_ENTITLEMENTS); } }), - MAIN_LAUNCHER_DESCRIPTION(cmd -> { - if (!cmd.isRuntime()) { - new LauncherVerifier(cmd).verify(cmd, LauncherVerifier.Action.VERIFY_DESCRIPTION); - } - }), MAIN_JAR_FILE(cmd -> { Optional.ofNullable(cmd.getArgumentValue("--main-jar", () -> null)).ifPresent(mainJar -> { TKit.assertFileExists(cmd.appLayout().appDirectory().resolve(mainJar)); @@ -1149,14 +1130,9 @@ public static enum StandardAssert { MacHelper.verifyBundleStructure(cmd); } }), - MAC_BUNDLE_UNSIGNED_SIGNATURE(cmd -> { - if (TKit.isOSX() && !MacHelper.appImageSigned(cmd)) { - MacHelper.verifyUnsignedBundleSignature(cmd); - } - }), ; - StandardAssert(Consumer action) { + AppLayoutAssert(Consumer action) { this.action = action; } @@ -1174,21 +1150,21 @@ private static JPackageCommand convertFromRuntime(JPackageCommand cmd) { private final Consumer action; } - public JPackageCommand setStandardAsserts(StandardAssert ... asserts) { + public JPackageCommand setAppLayoutAsserts(AppLayoutAssert ... asserts) { verifyMutable(); - standardAsserts = Set.of(asserts); + appLayoutAsserts = Set.of(asserts); return this; } - public JPackageCommand excludeStandardAsserts(StandardAssert... asserts) { + public JPackageCommand excludeAppLayoutAsserts(AppLayoutAssert... asserts) { var asSet = Set.of(asserts); - return setStandardAsserts(standardAsserts.stream().filter(Predicate.not( - asSet::contains)).toArray(StandardAssert[]::new)); + return setAppLayoutAsserts(appLayoutAsserts.stream().filter(Predicate.not( + asSet::contains)).toArray(AppLayoutAssert[]::new)); } - JPackageCommand runStandardAsserts() { - for (var standardAssert : standardAsserts.stream().sorted().toList()) { - standardAssert.action.accept(this); + JPackageCommand assertAppLayout() { + for (var appLayoutAssert : appLayoutAsserts.stream().sorted().toList()) { + appLayoutAssert.action.accept(this); } return this; } @@ -1280,7 +1256,10 @@ public void assertFileNotInAppImage(Path filename) { private void assertFileInAppImage(Path filename, Path expectedPath) { if (expectedPath != null) { - if (expectedPath.isAbsolute() || !expectedPath.getFileName().equals(filename.getFileName())) { + if (expectedPath.isAbsolute()) { + throw new IllegalArgumentException(); + } + if (!expectedPath.getFileName().equals(filename.getFileName())) { throw new IllegalArgumentException(); } } @@ -1366,7 +1345,7 @@ private JPackageCommand adjustArgumentsBeforeExecution() { addArguments("--runtime-image", DEFAULT_RUNTIME_IMAGE); } - if (!hasArgument("--verbose") && TKit.verboseJPackage() && !ignoreDefaultVerbose) { + if (!hasArgument("--verbose") && TKit.VERBOSE_JPACKAGE && !ignoreDefaultVerbose) { addArgument("--verbose"); } @@ -1390,7 +1369,11 @@ public void verifyIsOfType(PackageType ... types) { final var typesSet = Stream.of(types).collect(Collectors.toSet()); if (!hasArgument("--type")) { if (!isImagePackageType()) { - if ((TKit.isLinux() && typesSet.equals(PackageType.LINUX)) || (TKit.isWindows() && typesSet.equals(PackageType.WINDOWS))) { + if (TKit.isLinux() && typesSet.equals(PackageType.LINUX)) { + return; + } + + if (TKit.isWindows() && typesSet.equals(PackageType.WINDOWS)) { return; } @@ -1538,23 +1521,31 @@ public void run() { private Path winMsiLogFile; private Path unpackedPackageDirectory; private Set readOnlyPathAsserts = Set.of(ReadOnlyPathAssert.values()); - private Set standardAsserts = Set.of(StandardAssert.values()); + private Set appLayoutAsserts = Set.of(AppLayoutAssert.values()); private List>> outputValidators = new ArrayList<>(); - private static InheritableThreadLocal> defaultToolProvider = new InheritableThreadLocal<>() { - @Override - protected Optional initialValue() { - return Optional.empty(); - } - }; - - private static final Map PACKAGE_TYPES = Stream.of(PackageType.values()).collect(toMap(PackageType::getType, x -> x)); + private static Optional defaultToolProvider = Optional.empty(); - // Set the property to the path of run-time image to speed up - // building app images and platform bundles by avoiding running jlink. - // The value of the property will be automatically appended to - // jpackage command line if the command line doesn't have - // `--runtime-image` parameter set. - public static final Path DEFAULT_RUNTIME_IMAGE = Optional.ofNullable(TKit.getConfigProperty("runtime-image")).map(Path::of).orElse(null); + private static final Map PACKAGE_TYPES = Functional.identity( + () -> { + Map reply = new HashMap<>(); + for (PackageType type : PackageType.values()) { + reply.put(type.getType(), type); + } + return reply; + }).get(); + + public static final Path DEFAULT_RUNTIME_IMAGE = Functional.identity(() -> { + // Set the property to the path of run-time image to speed up + // building app images and platform bundles by avoiding running jlink + // The value of the property will be automativcally appended to + // jpackage command line if the command line doesn't have + // `--runtime-image` parameter set. + String val = TKit.getConfigProperty("runtime-image"); + if (val != null) { + return Path.of(val); + } + return null; + }).get(); // [HH:mm:ss.SSS] private static final Pattern TIMESTAMP_REGEXP = Pattern.compile( diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JarBuilder.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JarBuilder.java index c69c29af53a04..d62575d2fefcf 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JarBuilder.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JarBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -27,7 +27,6 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.List; -import java.util.Optional; /** @@ -49,11 +48,6 @@ public JarBuilder setMainClass(String v) { return this; } - public JarBuilder setRelease(int v) { - release = v; - return this; - } - public JarBuilder addSourceFile(Path v) { sourceFiles.add(v); return this; @@ -67,15 +61,11 @@ public JarBuilder setModuleVersion(String v) { public void create() { TKit.withTempDirectory("jar-workdir", workDir -> { if (!sourceFiles.isEmpty()) { - var exec = new Executor() + new Executor() .setToolProvider(JavaTool.JAVAC) - .addArguments("-d", workDir.toString()); - - Optional.ofNullable(release).ifPresent(r -> { - exec.addArguments("--release", r.toString()); - }); - - exec.addPathArguments(sourceFiles).execute(); + .addArguments("-d", workDir.toString()) + .addPathArguments(sourceFiles) + .execute(); } Files.createDirectories(outputJar.getParent()); @@ -102,5 +92,4 @@ public void create() { private Path outputJar; private String mainClass; private String moduleVersion; - private Integer release; } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherIconVerifier.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherIconVerifier.java index 79652a9828e00..6285d9d93a0df 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherIconVerifier.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherIconVerifier.java @@ -24,8 +24,8 @@ package jdk.jpackage.test; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; -import java.util.Optional; public final class LauncherIconVerifier { public LauncherIconVerifier() { @@ -38,33 +38,19 @@ public LauncherIconVerifier setLauncherName(String v) { public LauncherIconVerifier setExpectedIcon(Path v) { expectedIcon = v; - expectedDefault = false; return this; } public LauncherIconVerifier setExpectedDefaultIcon() { - expectedIcon = null; expectedDefault = true; return this; } - public LauncherIconVerifier setExpectedNoIcon() { - return setExpectedIcon(null); - } - public LauncherIconVerifier verifyFileInAppImageOnly(boolean v) { verifyFileInAppImageOnly = true; return this; } - public boolean expectDefaultIcon() { - return expectedDefault; - } - - public Optional expectIcon() { - return Optional.ofNullable(expectedIcon); - } - public void applyTo(JPackageCommand cmd) throws IOException { final String curLauncherName; final String label; @@ -85,13 +71,13 @@ public void applyTo(JPackageCommand cmd) throws IOException { WinExecutableIconVerifier.verifyLauncherIcon(cmd, launcherName, expectedIcon, expectedDefault); } } else if (expectedDefault) { - TKit.assertFileExists(iconPath); + TKit.assertPathExists(iconPath, true); } else if (expectedIcon == null) { TKit.assertPathExists(iconPath, false); } else { TKit.assertFileExists(iconPath); if (!verifyFileInAppImageOnly) { - TKit.assertSameFileContent(expectedIcon, iconPath, + TKit.assertTrue(-1 == Files.mismatch(expectedIcon, iconPath), String.format( "Check icon file [%s] of %s launcher is a copy of source icon file [%s]", iconPath, label, expectedIcon)); diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherVerifier.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherVerifier.java index 55cb38f21cfc9..87dc203daa148 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherVerifier.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherVerifier.java @@ -339,20 +339,9 @@ private void verifyMacEntitlements(JPackageCommand cmd) throws ParserConfigurati TKit.assertTrue(entitlements.isPresent(), String.format("Check [%s] launcher is signed with entitlements", name)); - var customFile = Optional.ofNullable(cmd.getArgumentValue("--mac-entitlements")).map(Path::of); - if (customFile.isEmpty()) { - // Try from the resource dir. - var resourceDirFile = Optional.ofNullable(cmd.getArgumentValue("--resource-dir")).map(Path::of).map(resourceDir -> { - return resourceDir.resolve(cmd.name() + ".entitlements"); - }).filter(Files::exists); - if (resourceDirFile.isPresent()) { - customFile = resourceDirFile; - } - } - Map expected; - if (customFile.isPresent()) { - expected = new PListReader(Files.readAllBytes(customFile.orElseThrow())).toMap(true); + if (cmd.hasArgument("--mac-entitlements")) { + expected = new PListReader(Files.readAllBytes(Path.of(cmd.getArgumentValue("--mac-entitlements")))).toMap(true); } else if (cmd.hasArgument("--mac-app-store")) { expected = DefaultEntitlements.APP_STORE; } else { diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java index 9776ab5c4c838..caec0e315c409 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java @@ -22,12 +22,6 @@ */ package jdk.jpackage.test; -import static jdk.jpackage.test.AdditionalLauncher.getAdditionalLauncherProperties; -import static java.util.Collections.unmodifiableSortedSet; -import static java.util.stream.Collectors.joining; -import static java.util.stream.Collectors.toMap; -import static java.util.stream.Collectors.toSet; - import java.io.IOException; import java.io.UncheckedIOException; import java.lang.reflect.InvocationTargetException; @@ -38,17 +32,17 @@ import java.util.Arrays; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Set; -import java.util.TreeMap; -import java.util.TreeSet; import java.util.function.Function; import java.util.function.Predicate; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; import java.util.stream.Stream; import jdk.jpackage.internal.util.PathUtils; import jdk.jpackage.internal.util.function.ThrowingConsumer; @@ -167,7 +161,8 @@ public static List getPrerequisitePackages(JPackageCommand cmd) { switch (packageType) { case LINUX_DEB: return Stream.of(getDebBundleProperty(cmd.outputBundle(), - "Depends").split(",")).map(String::strip).toList(); + "Depends").split(",")).map(String::strip).collect( + Collectors.toList()); case LINUX_RPM: return Executor.of("rpm", "-qp", "-R") @@ -328,9 +323,10 @@ static void verifyPackageBundleEssential(JPackageCommand cmd) { if (cmd.isRuntime()) { Path runtimeDir = cmd.appRuntimeDirectory(); Set expectedCriticalRuntimePaths = CRITICAL_RUNTIME_FILES.stream().map( - runtimeDir::resolve).collect(toSet()); + runtimeDir::resolve).collect(Collectors.toSet()); Set actualCriticalRuntimePaths = getPackageFiles(cmd).filter( - expectedCriticalRuntimePaths::contains).collect(toSet()); + expectedCriticalRuntimePaths::contains).collect( + Collectors.toSet()); checkPrerequisites = expectedCriticalRuntimePaths.equals( actualCriticalRuntimePaths); } else { @@ -376,7 +372,8 @@ static void addBundleDesktopIntegrationVerifier(PackageTest test, boolean integr Function, String> verifier = (lines) -> { // Lookup for xdg commands return lines.stream().filter(line -> { - Set words = Stream.of(line.split("\\s+")).collect(toSet()); + Set words = Stream.of(line.split("\\s+")).collect( + Collectors.toSet()); return words.contains("xdg-desktop-menu") || words.contains( "xdg-mime") || words.contains("xdg-icon-resource"); }).findFirst().orElse(null); @@ -392,7 +389,8 @@ static void addBundleDesktopIntegrationVerifier(PackageTest test, boolean integr Map> scriptlets = getScriptlets(cmd); if (integrated) { - var requiredScriptlets = Stream.of(Scriptlet.values()).sorted().toList(); + Set requiredScriptlets = Stream.of(Scriptlet.values()).sorted().collect( + Collectors.toSet()); TKit.assertTrue(scriptlets.keySet().containsAll( requiredScriptlets), String.format( "Check all required scriptlets %s found in the package. Package scriptlets: %s", @@ -454,29 +452,11 @@ static void verifyDesktopFiles(JPackageCommand cmd, boolean installed) { } private static Collection getDesktopFiles(JPackageCommand cmd) { - var unpackedDir = cmd.appLayout().desktopIntegrationDirectory(); - - return relativePackageFilesInSubdirectory(cmd, ApplicationLayout::desktopIntegrationDirectory) - .filter(path -> { - return path.getNameCount() == 1; - }) - .filter(path -> { - return ".desktop".equals(PathUtils.getSuffix(path)); - }) - .map(unpackedDir::resolve) - .toList(); - } - - private static Stream relativePackageFilesInSubdirectory( - JPackageCommand cmd, Function subdirFunc) { - - var unpackedDir = subdirFunc.apply(cmd.appLayout()); var packageDir = cmd.pathToPackageFile(unpackedDir); - return getPackageFiles(cmd).filter(path -> { - return path.startsWith(packageDir); - }).map(packageDir::relativize); + return packageDir.equals(path.getParent()) && path.getFileName().toString().endsWith(".desktop"); + }).map(Path::getFileName).map(unpackedDir::resolve).toList(); } private static String launcherNameFromDesktopFile(JPackageCommand cmd, Optional predefinedAppImage, Path desktopFile) { @@ -508,26 +488,13 @@ private static void verifyDesktopFile(JPackageCommand cmd, Optional mandatoryKeys = new TreeSet<>(Set.of("Name", "Comment", + final Set mandatoryKeys = new HashSet<>(Set.of("Name", "Comment", "Exec", "Icon", "Terminal", "Type", "Categories")); mandatoryKeys.removeAll(data.keySet()); TKit.assertTrue(mandatoryKeys.isEmpty(), String.format( "Check for missing %s keys in the file", mandatoryKeys)); - final String launcherDescription; - if (cmd.name().equals(launcherName) || predefinedAppImage.isPresent()) { - launcherDescription = Optional.ofNullable(cmd.getArgumentValue("--description")).orElseGet(cmd::name); - } else { - launcherDescription = getAdditionalLauncherProperties(cmd, launcherName).findProperty("description").or(() -> { - return Optional.ofNullable(cmd.getArgumentValue("--description")); - }).orElseGet(cmd::name); - } - - for (var e : List.of( - Map.entry("Type", "Application"), - Map.entry("Terminal", "false"), - Map.entry("Comment", launcherDescription) - )) { + for (var e : Map.of("Type", "Application", "Terminal", "false").entrySet()) { String key = e.getKey(); TKit.assertEquals(e.getValue(), data.find(key).orElseThrow(), String.format( "Check value of [%s] key", key)); @@ -743,7 +710,7 @@ private static Map> getScriptlets( private static Map> getDebScriptlets( JPackageCommand cmd, Set scriptlets) { - Map> result = new TreeMap<>(); + Map> result = new HashMap<>(); TKit.withTempDirectory("dpkg-control-files", tempDir -> { // Extract control Debian package files into temporary directory Executor.of("dpkg", "-e") @@ -765,7 +732,7 @@ private static Map> getRpmScriptlets( List output = Executor.of("rpm", "-qp", "--scripts", cmd.outputBundle().toString()).executeAndGetOutput(); - Map> result = new TreeMap<>(); + Map> result = new HashMap<>(); List curScriptletBody = null; for (String str : output) { Matcher m = Scriptlet.RPM_HEADER_PATTERN.matcher(str); @@ -799,10 +766,10 @@ private static enum Scriptlet { static final Pattern RPM_HEADER_PATTERN = Pattern.compile(String.format( "(%s) scriptlet \\(using /bin/sh\\):", Stream.of(values()).map( - v -> v.rpm).collect(joining("|")))); + v -> v.rpm).collect(Collectors.joining("|")))); static final Map RPM_MAP = Stream.of(values()).collect( - toMap(v -> v.rpm, v -> v)); + Collectors.toMap(v -> v.rpm, v -> v)); } public static String getDefaultPackageArch(PackageType type) { @@ -879,7 +846,7 @@ private static final class DesktopFile { } else { return Map.entry(components[0], components[1]); } - }).collect(toMap(Map.Entry::getKey, Map.Entry::getValue)); + }).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); } catch (IOException ex) { throw new UncheckedIOException(ex); } @@ -920,8 +887,7 @@ Optional findQuotedValue(String property) { private static final Pattern XDG_CMD_ICON_SIZE_PATTERN = Pattern.compile("\\s--size\\s+(\\d+)\\b"); // Values grabbed from https://linux.die.net/man/1/xdg-icon-resource - private static final Set XDG_CMD_VALID_ICON_SIZES = unmodifiableSortedSet( - new TreeSet<>(List.of(16, 22, 32, 48, 64, 128))); + private static final Set XDG_CMD_VALID_ICON_SIZES = Set.of(16, 22, 32, 48, 64, 128); private static final Method getServiceUnitFileName = initGetServiceUnitFileName(); } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacHelper.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacHelper.java index 3900851f81009..d01536e327db5 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacHelper.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacHelper.java @@ -52,9 +52,7 @@ import java.util.Optional; import java.util.Properties; import java.util.Set; -import java.util.function.BiConsumer; import java.util.function.BiFunction; -import java.util.function.Consumer; import java.util.function.Function; import java.util.regex.Pattern; import java.util.stream.Collectors; @@ -68,7 +66,6 @@ import jdk.jpackage.internal.util.XmlUtils; import jdk.jpackage.internal.util.function.ThrowingConsumer; import jdk.jpackage.internal.util.function.ThrowingSupplier; -import jdk.jpackage.test.MacSign.CertificateRequest; import jdk.jpackage.test.PackageTest.PackageHandlers; public final class MacHelper { @@ -232,61 +229,25 @@ private static void collectPListProperty(Map accumulator, String } } - /** - * Returns {@code true} if the given jpackage command line is configured to sign - * predefined app image in place. - *

    - * jpackage will not create a new app image or a native bundle. - * - * @param cmd the jpackage command to examine - * @return {@code true} if the given jpackage command line is configured to sign - * predefined app image in place and {@code false} otherwise. - */ public static boolean signPredefinedAppImage(JPackageCommand cmd) { Objects.requireNonNull(cmd); if (!TKit.isOSX()) { throw new UnsupportedOperationException(); } - return cmd.hasArgument("--mac-sign") && cmd.hasArgument("--app-image") && cmd.isImagePackageType(); - } - - /** - * Returns {@code true} if the given jpackage command line is configured such - * that the app image it will produce will be signed. - *

    - * If the jpackage command line is bundling a native package, the function - * returns {@code true} if the bundled app image will be signed. - * - * @param cmd the jpackage command to examine - * @return {@code true} if the given jpackage command line is configured such - * that the app image it will produce will be signed and {@code false} - * otherwise. - */ + return cmd.hasArgument("--mac-sign") && cmd.hasArgument("--app-image"); + } + public static boolean appImageSigned(JPackageCommand cmd) { Objects.requireNonNull(cmd); if (!TKit.isOSX()) { throw new UnsupportedOperationException(); } - var runtimeImage = Optional.ofNullable(cmd.getArgumentValue("--runtime-image")).map(Path::of); - var appImage = Optional.ofNullable(cmd.getArgumentValue("--app-image")).map(Path::of); - - if (cmd.isRuntime() && Files.isDirectory(runtimeImage.orElseThrow().resolve("Contents/_CodeSignature"))) { - // If the predefined runtime is a signed bundle, bundled image should be signed too. - return true; - } else if (appImage.map(AppImageFile::load).map(AppImageFile::macSigned).orElse(false)) { + if (Optional.ofNullable(cmd.getArgumentValue("--app-image")).map(Path::of).map(AppImageFile::load).map(AppImageFile::macSigned).orElse(false)) { // The external app image is signed, so the app image is signed too. return true; } - if (!cmd.isImagePackageType() && appImage.isPresent()) { - // Building a ".pkg" or a ".dmg" bundle from the predefined app image. - // The predefined app image is unsigned, so the app image bundled - // in the output native package will be unsigned too - // (even if the ".pkg" file may be signed itself, and we never sign ".dmg" files). - return false; - } - if (!cmd.hasArgument("--mac-sign")) { return false; } @@ -371,110 +332,6 @@ public static void writeFaPListFragment(JPackageCommand cmd, XMLStreamWriter xml }).run(); } - public static Consumer useKeychain(MacSign.ResolvedKeychain keychain) { - return useKeychain(keychain.spec().keychain()); - } - - public static Consumer useKeychain(MacSign.Keychain keychain) { - return cmd -> { - useKeychain(cmd, keychain); - }; - } - - public static JPackageCommand useKeychain(JPackageCommand cmd, MacSign.ResolvedKeychain keychain) { - return useKeychain(cmd, keychain.spec().keychain()); - } - - public static JPackageCommand useKeychain(JPackageCommand cmd, MacSign.Keychain keychain) { - return sign(cmd).addArguments("--mac-signing-keychain", keychain.name()); - } - - public static JPackageCommand sign(JPackageCommand cmd) { - if (!cmd.hasArgument("--mac-sign")) { - cmd.addArgument("--mac-sign"); - } - return cmd; - } - - public record SignKeyOption(Type type, CertificateRequest certRequest) { - - public SignKeyOption { - Objects.requireNonNull(type); - Objects.requireNonNull(certRequest); - } - - public enum Type { - SIGN_KEY_USER_NAME, - SIGN_KEY_IDENTITY, - ; - } - - @Override - public String toString() { - var sb = new StringBuffer(); - applyTo((optionName, _) -> { - sb.append(String.format("{%s: %s}", optionName, certRequest)); - }); - return sb.toString(); - } - - public JPackageCommand addTo(JPackageCommand cmd) { - applyTo(cmd::addArguments); - return sign(cmd); - } - - public JPackageCommand setTo(JPackageCommand cmd) { - applyTo(cmd::setArgumentValue); - return sign(cmd); - } - - private void applyTo(BiConsumer sink) { - switch (certRequest.type()) { - case INSTALLER -> { - switch (type) { - case SIGN_KEY_IDENTITY -> { - sink.accept("--mac-installer-sign-identity", certRequest.name()); - return; - } - case SIGN_KEY_USER_NAME -> { - sink.accept("--mac-signing-key-user-name", certRequest.shortName()); - return; - } - } - } - case CODE_SIGN -> { - switch (type) { - case SIGN_KEY_IDENTITY -> { - sink.accept("--mac-app-image-sign-identity", certRequest.name()); - return; - } - case SIGN_KEY_USER_NAME -> { - sink.accept("--mac-signing-key-user-name", certRequest.shortName()); - return; - } - } - } - } - - throw new AssertionError(); - } - } - - static void verifyUnsignedBundleSignature(JPackageCommand cmd) { - if (!cmd.isImagePackageType()) { - MacSignVerify.assertUnsigned(cmd.outputBundle()); - } - - final Path bundleRoot; - if (cmd.isImagePackageType()) { - bundleRoot = cmd.outputBundle(); - } else { - bundleRoot = cmd.pathToUnpackedPackageFile(cmd.appInstallationDirectory()); - } - - MacSignVerify.assertAdhocSigned(bundleRoot); - } - static PackageHandlers createDmgPackageHandlers() { return new PackageHandlers(MacHelper::installDmg, MacHelper::uninstallDmg, MacHelper::unpackDmg); } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacSign.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacSign.java index 7d2bb908edbac..af9f57c4f7f47 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacSign.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacSign.java @@ -59,7 +59,6 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; -import java.util.function.Consumer; import java.util.function.Predicate; import java.util.stream.Stream; import javax.naming.ldap.LdapName; @@ -352,52 +351,6 @@ private String validatedPassword() { private String password; } - public static final class UsageBuilder { - - UsageBuilder(Collection keychains) { - this.keychains = List.copyOf(keychains); - } - - public void run(Runnable runnable) { - Objects.requireNonNull(runnable); - - final Optional> oldKeychains; - if (addToSearchList) { - oldKeychains = Optional.ofNullable(activeKeychainFiles()); - Keychain.addToSearchList(keychains); - } else { - oldKeychains = Optional.empty(); - } - - try { - // Ensure keychains to be used for signing are unlocked. - // When the codesign command operates on a locked keychain in a ssh session - // it emits cryptic "errSecInternalComponent" error without other details. - keychains.forEach(Keychain::unlock); - runnable.run(); - } finally { - oldKeychains.ifPresent(restoreKeychains -> { - security("list-keychains", "-d", "user", "-s") - .addArguments(restoreKeychains.stream().map(Path::toString).toList()) - .execute(); - }); - } - } - - public UsageBuilder addToSearchList(boolean v) { - addToSearchList = v; - return this; - } - - public UsageBuilder addToSearchList() { - return addToSearchList(true); - } - - private final Collection keychains; - private boolean addToSearchList; - } - - Keychain create() { final var exec = createExecutor("create-keychain"); final var result = exec.saveOutput().executeWithoutExitCodeCheck(); @@ -462,12 +415,24 @@ List findCertificates() { return certs; } - static void addToSearchList(Collection keychains) { + public static void addToSearchList(Collection keychains) { security("list-keychains", "-d", "user", "-s", "login.keychain") .addArguments(keychains.stream().map(Keychain::name).toList()) .execute(); } + public static void withAddedKeychains(Collection keychains, Runnable runnable) { + final var curKeychains = activeKeychainFiles(); + addToSearchList(keychains); + try { + runnable.run(); + } finally { + security("list-keychains", "-d", "user", "-s") + .addArguments(curKeychains.stream().map(Path::toString).toList()) + .execute(); + } + } + private static List activeKeychainFiles() { // $ security list-keychains // "/Users/alexeysemenyuk/Library/Keychains/login.keychain-db" @@ -1072,47 +1037,6 @@ public static boolean isDeployed(List specs) { return !missingKeychain && !missingCertificates && !invalidCertificates; } - public static Keychain.UsageBuilder withKeychains(KeychainWithCertsSpec... keychains) { - return withKeychains(Stream.of(keychains).map(KeychainWithCertsSpec::keychain).toArray(Keychain[]::new)); - } - - public static Keychain.UsageBuilder withKeychains(Keychain... keychains) { - return new Keychain.UsageBuilder(List.of(keychains)); - } - - public static void withKeychains(Runnable runnable, Consumer mutator, Keychain... keychains) { - Objects.requireNonNull(runnable); - var builder = withKeychains(keychains); - mutator.accept(builder); - builder.run(runnable); - } - - public static void withKeychains(Runnable runnable, Keychain... keychains) { - withKeychains(runnable, _ -> {}, keychains); - } - - public static void withKeychain(Consumer consumer, Consumer mutator, Keychain keychain) { - Objects.requireNonNull(consumer); - withKeychains(() -> { - consumer.accept(keychain); - }, mutator, keychain); - } - - public static void withKeychain(Consumer consumer, Keychain keychain) { - withKeychain(consumer, _ -> {}, keychain); - } - - public static void withKeychain(Consumer consumer, Consumer mutator, ResolvedKeychain keychain) { - Objects.requireNonNull(consumer); - withKeychains(() -> { - consumer.accept(keychain); - }, mutator, keychain.spec().keychain()); - } - - public static void withKeychain(Consumer consumer, ResolvedKeychain keychain) { - withKeychain(consumer, _ -> {}, keychain); - } - public static final class ResolvedKeychain { public ResolvedKeychain(KeychainWithCertsSpec spec) { this.spec = Objects.requireNonNull(spec); @@ -1122,10 +1046,6 @@ public KeychainWithCertsSpec spec() { return spec; } - public String name() { - return spec.keychain().name(); - } - public Map mapCertificateRequests() { if (certMap == null) { synchronized (this) { diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacSignVerify.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacSignVerify.java index 81d31ed726789..ae27e292bf676 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacSignVerify.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacSignVerify.java @@ -44,43 +44,6 @@ */ public final class MacSignVerify { - public static void verifyAppImageSigned( - JPackageCommand cmd, CertificateRequest certRequest, MacSign.ResolvedKeychain keychain) { - - cmd.verifyIsOfType(PackageType.MAC); - Objects.requireNonNull(certRequest); - Objects.requireNonNull(keychain); - - final Path bundleRoot; - if (cmd.isImagePackageType()) { - bundleRoot = cmd.outputBundle(); - } else { - bundleRoot = cmd.pathToUnpackedPackageFile( - cmd.appInstallationDirectory()); - } - - assertSigned(bundleRoot, certRequest); - - if (!cmd.isRuntime()) { - cmd.addLauncherNames().stream().map(cmd::appLauncherPath).forEach(launcherPath -> { - assertSigned(launcherPath, certRequest); - }); - } - - // Set to "null" if the sign origin is not found, instead of bailing out with an exception. - // Let is fail in the following TKit.assertEquals() call with a proper log message. - var signOrigin = findSpctlSignOrigin(SpctlType.EXEC, bundleRoot).orElse(null); - - TKit.assertEquals(certRequest.name(), signOrigin, - String.format("Check [%s] has sign origin as expected", bundleRoot)); - } - - public static void verifyPkgSigned(JPackageCommand cmd, CertificateRequest certRequest, MacSign.ResolvedKeychain keychain) { - cmd.verifyIsOfType(PackageType.MAC_PKG); - assertPkgSigned(cmd.outputBundle(), certRequest, - Objects.requireNonNull(keychain.mapCertificateRequests().get(certRequest))); - } - public static void assertSigned(Path path, CertificateRequest certRequest) { assertSigned(path); TKit.assertEquals(certRequest.name(), findCodesignSignOrigin(path).orElse(null), @@ -151,8 +114,8 @@ public static Optional findSpctlSignOrigin(SpctlType type, Path path) { } public static Optional findCodesignSignOrigin(Path path) { - final var exec = Executor.of("/usr/bin/codesign", "--display", "--verbose=4", path.toString()); - final var result = exec.saveOutput().executeWithoutExitCodeCheck(); + final var exec = Executor.of("/usr/bin/codesign", "--display", "--verbose=4", path.toString()).saveOutput(); + final var result = exec.executeWithoutExitCodeCheck(); if (result.getExitCode() == 0) { return Optional.of(result.getOutput().stream().map(line -> { if (line.equals("Signature=adhoc")) { @@ -181,34 +144,12 @@ public static Optional findCodesignSignOrigin(Path path) { } public static void assertSigned(Path path) { - assertSigned(path, false); - } - - private static void assertSigned(Path path, boolean sudo) { - final Executor exec; - if (sudo) { - exec = Executor.of("sudo", "/usr/bin/codesign"); - } else { - exec = Executor.of("/usr/bin/codesign"); - } - exec.addArguments("--verify", "--deep", "--strict", "--verbose=2", path.toString()); - final var result = exec.saveOutput().executeWithoutExitCodeCheck(); - if (result.getExitCode() == 0) { - TKit.TextStreamVerifier.group() - .add(TKit.assertTextStream(": valid on disk").predicate(String::endsWith)) - .add(TKit.assertTextStream(": satisfies its Designated Requirement").predicate(String::endsWith)) - .create().accept(result.getOutput().iterator()); - } else if (!sudo && result.getOutput().stream().findFirst().filter(str -> { - // By some reason /usr/bin/codesign command fails for some installed bundles. - // It is known to fail for some AppContentTest test cases and all FileAssociationsTest test cases. - // Rerunning the command with "sudo" works, though. - return str.equals(String.format("%s: Permission denied", path)); - }).isPresent()) { - TKit.trace("Try /usr/bin/codesign again with `sudo`"); - assertSigned(path, true); - } else { - reportUnexpectedCommandOutcome(exec.getPrintableCommandLine(), result); - } + final var verifier = TKit.TextStreamVerifier.group() + .add(TKit.assertTextStream(": valid on disk").predicate(String::endsWith)) + .add(TKit.assertTextStream(": satisfies its Designated Requirement").predicate(String::endsWith)) + .create(); + verifier.accept(Executor.of("/usr/bin/codesign", "--verify", "--deep", + "--strict", "--verbose=2", path.toString()).executeAndGetOutput().iterator()); } public static List getPkgCertificateChain(Path path) { diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Main.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Main.java index fa8fe166f5a33..e7f06b0d60852 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Main.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Main.java @@ -41,11 +41,11 @@ public final class Main { - public static void main(String... args) throws Throwable { + public static void main(String args[]) throws Throwable { main(TestBuilder.build(), args); } - public static void main(TestBuilder.Builder builder, String... args) throws Throwable { + public static void main(TestBuilder.Builder builder, String args[]) throws Throwable { boolean listTests = false; List tests = new ArrayList<>(); try (TestBuilder testBuilder = builder.testConsumer(tests::add).create()) { diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/ObjectMapper.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/ObjectMapper.java deleted file mode 100644 index f35e255951eeb..0000000000000 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/ObjectMapper.java +++ /dev/null @@ -1,780 +0,0 @@ -/* - * 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 jdk.jpackage.test; - -import static java.util.stream.Collectors.groupingBy; -import static java.util.stream.Collectors.toSet; -import static jdk.jpackage.internal.util.function.ExceptionBox.rethrowUnchecked; -import static jdk.jpackage.internal.util.function.ThrowingConsumer.toConsumer; -import static jdk.jpackage.internal.util.function.ThrowingRunnable.toRunnable; -import static jdk.jpackage.internal.util.function.ThrowingSupplier.toSupplier; - -import java.lang.reflect.Array; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.math.BigInteger; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.UUID; -import java.util.function.BiConsumer; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.function.IntPredicate; -import java.util.function.Predicate; -import java.util.function.Supplier; -import java.util.stream.Collector; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import javax.xml.stream.XMLStreamWriter; -import jdk.jpackage.internal.util.IdentityWrapper; - -public final class ObjectMapper { - - private ObjectMapper( - Predicate classFilter, - Predicate> methodFilter, - Predicate leafClassFilter, - Map> substitutes, - Map, BiConsumer>> mutators, - Set accessPackageMethods) { - - this.classFilter = Objects.requireNonNull(classFilter); - this.methodFilter = Objects.requireNonNull(methodFilter); - this.leafClassFilter = Objects.requireNonNull(leafClassFilter); - this.substitutes = Objects.requireNonNull(substitutes); - this.mutators = Objects.requireNonNull(mutators); - this.accessPackageMethods = accessPackageMethods; - } - - public static Builder blank() { - return new Builder().allowAllLeafClasses(false).exceptLeafClasses().add(Stream.of( - Object.class, - String.class, String[].class, - boolean.class, Boolean.class, boolean[].class, Boolean[].class, - byte.class, Byte.class, byte[].class, Byte[].class, - char.class, Character.class, char[].class, Character[].class, - short.class, Short.class, short[].class, Short[].class, - int.class, Integer.class, int[].class, Integer[].class, - long.class, Long.class, long[].class, Long[].class, - float.class, Float.class, float[].class, Float[].class, - double.class, Double.class, double[].class, Double[].class, - void.class, Void.class, Void[].class - ).map(Class::getName).toList()).apply(); - } - - public static Builder standard() { - return blank() - .mutate(configureObject()) - .mutate(configureLeafClasses()) - .mutate(configureOptional()) - .mutate(configureFunctionalTypes()) - .mutate(configureEnum()) - .mutate(configureException()); - } - - public static Consumer configureObject() { - // Exclude all method of Object class. - return builder -> { - builder.exceptMethods().add(OBJECT_METHODS).apply(); - }; - } - - public static Consumer configureLeafClasses() { - return builder -> { - builder.exceptLeafClasses().add(Stream.of( - IdentityWrapper.class, - Class.class, - Path.class, - Path.of("").getClass(), - UUID.class, - BigInteger.class - ).map(Class::getName).toList()).apply(); - }; - } - - public static Consumer configureOptional() { - return builder -> { - // Filter out all but "get()" methods of "Optional" class. - builder.exceptAllMethods(Optional.class).remove("get").apply(); - // Substitute "Optional.get()" with the function that will return "null" if the value is "null". - builder.subst(Optional.class, "get", opt -> { - if (opt.isPresent()) { - return opt.get(); - } else { - return null; - } - }); - }; - } - - public static Consumer configureFunctionalTypes() { - // Remove all getters from the standard functional types. - return builder -> { - builder.exceptAllMethods(Predicate.class).apply(); - builder.exceptAllMethods(Supplier.class).apply(); - }; - } - - public static Consumer configureEnum() { - return builder -> { - // Filter out "getDeclaringClass()" and "describeConstable()" methods of "Enum" class. - builder.exceptSomeMethods(Enum.class).add("getDeclaringClass", "describeConstable").apply(); - }; - } - - public static Consumer configureException() { - return builder -> { - // Include only "getMessage()" and "getCause()" methods of "Exception" class. - builder.exceptAllMethods(Exception.class).remove("getMessage", "getCause").apply(); - builder.mutator(Exception.class, (ex, map) -> { - var eit = map.entrySet().iterator(); - while (eit.hasNext()) { - var e = eit.next(); - if (e.getValue() == NULL) { - // Remove property with the "null" value. - eit.remove(); - } - } - map.put("getClass", ex.getClass().getName()); - }); - }; - } - - public static String lookupFullMethodName(Method m) { - return lookupFullMethodName(m.getDeclaringClass(), m.getName()); - } - - public static String lookupFullMethodName(Class c, String m) { - return Objects.requireNonNull(c).getName() + lookupMethodName(m); - } - - public static String lookupMethodName(Method m) { - return lookupMethodName(m.getName()); - } - - public static String lookupMethodName(String m) { - return "#" + Objects.requireNonNull(m); - } - - public static Object wrapIdentity(Object v) { - if (v instanceof IdentityWrapper wrapper) { - return wrapper; - } else { - return new IdentityWrapper(v); - } - } - - public static void store(Map map, XMLStreamWriter xml) { - XmlWriter.writePropertyMap(map, xml); - } - - @SuppressWarnings("unchecked") - public static Optional findNonNullProperty(Map map, String propertyName) { - Objects.requireNonNull(propertyName); - Objects.requireNonNull(map); - - return Optional.ofNullable(map.get(propertyName)).filter(Predicate.not(NULL::equals)).map(v -> { - return (T)v; - }); - } - - public Object map(Object obj) { - if (obj != null) { - return mapObject(obj).orElseGet(Map::of); - } else { - return null; - } - } - - @SuppressWarnings("unchecked") - public Map toMap(Object obj) { - if (obj == null) { - return null; - } else { - var mappedObj = map(obj); - if (mappedObj instanceof Map m) { - return (Map)m; - } else { - return Map.of("value", mappedObj); - } - } - } - - public Optional mapObject(Object obj) { - if (obj == null) { - return Optional.empty(); - } - - if (leafClassFilter.test(obj.getClass().getName())) { - return Optional.of(obj); - } - - if (!filter(obj.getClass())) { - return Optional.empty(); - } - - if (obj instanceof Iterable col) { - return Optional.of(mapIterable(col)); - } - - if (obj instanceof Map map) { - return Optional.of(mapMap(map)); - } - - if (obj.getClass().isArray()) { - return Optional.of(mapArray(obj)); - } - - var theMap = getMethods(obj).map(m -> { - final Object propertyValue; - final var subst = substitutes.get(m); - if (subst != null) { - propertyValue = applyGetter(obj, subst); - } else { - propertyValue = invoke(m, obj); - } - return Map.entry(m.getName(), mapObject(propertyValue).orElse(NULL)); - }).collect(toMutableMap(Map.Entry::getKey, Map.Entry::getValue)); - - mutators.entrySet().stream().filter(m -> { - return m.getKey().isInstance(obj); - }).findFirst().ifPresent(m -> { - m.getValue().accept(obj, theMap); - }); - - if (theMap.isEmpty()) { - return Optional.of(wrapIdentity(obj)); - } - - return Optional.of(theMap); - } - - private Object invoke(Method m, Object obj) { - try { - return m.invoke(obj); - } catch (IllegalAccessException ex) { - throw rethrowUnchecked(ex); - } catch (InvocationTargetException ex) { - return map(ex.getTargetException()); - } - } - - private Collection mapIterable(Iterable col) { - final List list = new ArrayList<>(); - for (var obj : col) { - list.add(mapObject(obj).orElse(NULL)); - } - return list; - } - - private Map mapMap(Map map) { - return map.entrySet().stream().collect(toMutableMap(e -> { - return mapObject(e.getKey()).orElse(NULL); - }, e -> { - return mapObject(e.getValue()).orElse(NULL); - })); - } - - private Object mapArray(Object arr) { - final var len = Array.getLength(arr); - - if (len == 0) { - return arr; - } - - Object[] buf = null; - - for (int i = 0; i != len; i++) { - var from = Array.get(arr, i); - if (from != null) { - var to = mapObject(from).orElseThrow(); - if (from != to || buf != null) { - if (buf == null) { - buf = (Object[])Array.newInstance(Object.class, len); - System.arraycopy(arr, 0, buf, 0, i); - } - buf[i] = to; - } - } - } - - return Optional.ofNullable((Object)buf).orElse(arr); - } - - @SuppressWarnings("unchecked") - private static Object applyGetter(Object obj, Function getter) { - return getter.apply((T)obj); - } - - private boolean filter(Class type) { - return classFilter.test(type.getName()); - } - - private boolean filter(Method m) { - return methodFilter.test(List.of(lookupMethodName(m), lookupFullMethodName(m))); - } - - private Stream getMethods(Object obj) { - return MethodGroups.create(obj.getClass(), accessPackageMethods).filter(this::filter).map(MethodGroup::callable); - } - - private static boolean defaultFilter(Method m) { - if (Modifier.isStatic(m.getModifiers()) || (m.getParameterCount() > 0) || void.class.equals(m.getReturnType())) { - return false; - } - return true; - } - - private static - Collector> toMutableMap(Function keyMapper, - Function valueMapper) { - return Collectors.toMap(keyMapper, valueMapper, (x , y) -> { - throw new UnsupportedOperationException( - String.format("Entries with the same key and different values [%s] and [%s]", x, y)); - }, HashMap::new); - } - - public static final class Builder { - - private Builder() { - allowAllClasses(); - allowAllLeafClasses(); - allowAllMethods(); - } - - public ObjectMapper create() { - return new ObjectMapper( - classFilter.createPredicate(), - methodFilter.createMultiPredicate(), - leafClassFilter.createPredicate(), - Map.copyOf(substitutes), - Map.copyOf(mutators), - accessPackageMethods); - } - - - public final class NamePredicateBuilder { - - NamePredicateBuilder(Filter sink) { - this.sink = Objects.requireNonNull(sink); - } - - public Builder apply() { - sink.addAll(items); - return Builder.this; - } - - public NamePredicateBuilder add(String... v) { - return add(List.of(v)); - } - - public NamePredicateBuilder add(Collection v) { - items.addAll(v); - return this; - } - - private final Filter sink; - private final Set items = new HashSet<>(); - } - - - public final class AllMethodPredicateBuilder { - - AllMethodPredicateBuilder(Class type) { - impl = new MethodPredicateBuilder(type, false); - } - - public AllMethodPredicateBuilder remove(String... v) { - return remove(List.of(v)); - } - - public AllMethodPredicateBuilder remove(Collection v) { - impl.add(v); - return this; - } - - public Builder apply() { - return impl.apply(); - } - - private final MethodPredicateBuilder impl; - } - - - public final class SomeMethodPredicateBuilder { - - SomeMethodPredicateBuilder(Class type) { - impl = new MethodPredicateBuilder(type, true); - } - - public SomeMethodPredicateBuilder add(String... v) { - return add(List.of(v)); - } - - public SomeMethodPredicateBuilder add(Collection v) { - impl.add(v); - return this; - } - - public Builder apply() { - return impl.apply(); - } - - private final MethodPredicateBuilder impl; - } - - - public Builder allowAllClasses(boolean v) { - classFilter.negate(v); - return this; - } - - public Builder allowAllClasses() { - return allowAllClasses(true); - } - - public Builder allowAllMethods(boolean v) { - methodFilter.negate(v); - return this; - } - - public Builder allowAllMethods() { - return allowAllMethods(true); - } - - public Builder allowAllLeafClasses(boolean v) { - leafClassFilter.negate(v); - return this; - } - - public Builder allowAllLeafClasses() { - return allowAllLeafClasses(true); - } - - public NamePredicateBuilder exceptClasses() { - return new NamePredicateBuilder(classFilter); - } - - public AllMethodPredicateBuilder exceptAllMethods(Class type) { - return new AllMethodPredicateBuilder(type); - } - - public SomeMethodPredicateBuilder exceptSomeMethods(Class type) { - return new SomeMethodPredicateBuilder(type); - } - - public NamePredicateBuilder exceptMethods() { - return new NamePredicateBuilder(methodFilter); - } - - public NamePredicateBuilder exceptLeafClasses() { - return new NamePredicateBuilder(leafClassFilter); - } - - public Builder subst(Method target, Function substitute) { - substitutes.put(Objects.requireNonNull(target), Objects.requireNonNull(substitute)); - return this; - } - - public Builder subst(Class targetClass, String targetMethodName, Function substitute) { - var method = toSupplier(() -> targetClass.getMethod(targetMethodName)).get(); - return subst(method, substitute); - } - - public Builder mutator(Class targetClass, BiConsumer> mutator) { - mutators.put(Objects.requireNonNull(targetClass), Objects.requireNonNull(mutator)); - return this; - } - - public Builder mutate(Consumer mutator) { - mutator.accept(this); - return this; - } - - public Builder accessPackageMethods(Package... packages) { - Stream.of(packages).map(Package::getName).forEach(accessPackageMethods::add); - return this; - } - - - private final class MethodPredicateBuilder { - - MethodPredicateBuilder(Class type, boolean negate) { - this.type = Objects.requireNonNull(type); - buffer.negate(negate); - } - - void add(Collection v) { - buffer.addAll(v); - } - - Builder apply() { - var pred = buffer.createPredicate(); - - var items = MethodGroups.create(type, accessPackageMethods).groups().stream().map(MethodGroup::primary).filter(m -> { - return !OBJECT_METHODS.contains(ObjectMapper.lookupMethodName(m)); - }).filter(m -> { - return !pred.test(m.getName()); - }).map(ObjectMapper::lookupFullMethodName).toList(); - - return exceptMethods().add(items).apply(); - } - - private final Class type; - private final Filter buffer = new Filter(); - } - - - private static final class Filter { - Predicate> createMultiPredicate() { - if (items.isEmpty()) { - var match = negate; - return v -> match; - } else if (negate) { - return v -> { - return v.stream().noneMatch(Set.copyOf(items)::contains); - }; - } else { - return v -> { - return v.stream().anyMatch(Set.copyOf(items)::contains); - }; - } - } - - Predicate createPredicate() { - if (items.isEmpty()) { - var match = negate; - return v -> match; - } else if (negate) { - return Predicate.not(Set.copyOf(items)::contains); - } else { - return Set.copyOf(items)::contains; - } - } - - void addAll(Collection v) { - items.addAll(v); - } - - void negate(boolean v) { - negate = v; - } - - private boolean negate; - private final Set items = new HashSet<>(); - } - - - private final Filter classFilter = new Filter(); - private final Filter methodFilter = new Filter(); - private final Filter leafClassFilter = new Filter(); - private final Map> substitutes = new HashMap<>(); - private final Map, BiConsumer>> mutators = new HashMap<>(); - private final Set accessPackageMethods = new HashSet<>(); - } - - - private record MethodGroup(List methods) { - - MethodGroup { - Objects.requireNonNull(methods); - - if (methods.isEmpty()) { - throw new IllegalArgumentException(); - } - - methods.stream().map(Method::getName).reduce((a, b) -> { - if (!a.equals(b)) { - throw new IllegalArgumentException(); - } else { - return a; - } - }); - } - - Method callable() { - var primary = primary(); - if (!primary.getDeclaringClass().isInterface()) { - primary = methods.stream().filter(m -> { - return m.getDeclaringClass().isInterface(); - }).findFirst().orElse(primary); - } - return primary; - } - - Method primary() { - return methods.getFirst(); - } - - boolean match(Predicate predicate) { - Objects.requireNonNull(predicate); - return methods.stream().allMatch(predicate); - } - } - - - private record MethodGroups(Collection groups) { - - MethodGroups { - Objects.requireNonNull(groups); - } - - Stream filter(Predicate predicate) { - Objects.requireNonNull(predicate); - - return groups.stream().filter(g -> { - return g.match(predicate); - }); - } - - static MethodGroups create(Class type, Set accessPackageMethods) { - List> types = new ArrayList<>(); - - collectSuperclassAndInterfaces(type, types::add); - - final var methodGroups = types.stream() - .map(c -> { - if (accessPackageMethods.contains(c.getPackageName())) { - return PUBLIC_AND_PACKAGE_METHODS_GETTER.apply(c); - } else { - return PUBLIC_METHODS_GETTER.apply(c); - } - }) - .flatMap(x -> x) - .filter(ObjectMapper::defaultFilter) - .collect(groupingBy(Method::getName)); - - return new MethodGroups(methodGroups.values().stream().distinct().map(MethodGroup::new).toList()); - } - - private static void collectSuperclassAndInterfaces(Class type, Consumer> sink) { - Objects.requireNonNull(type); - Objects.requireNonNull(sink); - - for (; type != null; type = type.getSuperclass()) { - sink.accept(type); - for (var i : type.getInterfaces()) { - collectSuperclassAndInterfaces(i, sink); - } - } - } - } - - - private static final class XmlWriter { - static void write(Object obj, XMLStreamWriter xml) { - if (obj instanceof Map map) { - writePropertyMap(map, xml); - } else if (obj instanceof Collection col) { - writeCollection(col, xml); - } else if (obj.getClass().isArray()) { - writeArray(obj, xml); - } else { - toRunnable(() -> xml.writeCharacters(obj.toString())).run(); - } - } - - private static void writePropertyMap(Map map, XMLStreamWriter xml) { - map.entrySet().stream().sorted(Comparator.comparing(e -> e.getKey().toString())).forEach(toConsumer(e -> { - xml.writeStartElement("property"); - xml.writeAttribute("name", e.getKey().toString()); - write(e.getValue(), xml); - xml.writeEndElement(); - })); - } - - private static void writeCollection(Collection col, XMLStreamWriter xml) { - try { - xml.writeStartElement("collection"); - xml.writeAttribute("size", Integer.toString(col.size())); - for (var item : col) { - xml.writeStartElement("item"); - write(item, xml); - xml.writeEndElement(); - } - xml.writeEndElement(); - } catch (Exception ex) { - rethrowUnchecked(ex); - } - } - - private static void writeArray(Object arr, XMLStreamWriter xml) { - var len = Array.getLength(arr); - try { - xml.writeStartElement("array"); - xml.writeAttribute("size", Integer.toString(len)); - for (int i = 0; i != len; i++) { - xml.writeStartElement("item"); - write(Array.get(arr, i), xml); - xml.writeEndElement(); - } - xml.writeEndElement(); - } catch (Exception ex) { - rethrowUnchecked(ex); - } - } - } - - - private final Predicate classFilter; - private final Predicate> methodFilter; - private final Predicate leafClassFilter; - private final Map> substitutes; - private final Map, BiConsumer>> mutators; - private final Set accessPackageMethods; - - static final Object NULL = new Object() { - @Override - public String toString() { - return ""; - } - }; - - private static final Set OBJECT_METHODS = - Stream.of(Object.class.getMethods()).map(ObjectMapper::lookupMethodName).collect(toSet()); - - private static final Function, Stream> PUBLIC_METHODS_GETTER = type -> { - return Stream.of(type.getMethods()); - }; - - private static final Function, Stream> PUBLIC_AND_PACKAGE_METHODS_GETTER = type -> { - return Stream.of(type.getDeclaredMethods()).filter(m -> { - return Stream.of(Modifier::isPrivate, Modifier::isProtected).map(p -> { - return p.test(m.getModifiers()); - }).allMatch(v -> !v); - }).map(m -> { - m.setAccessible(true); - return m; - }); - }; -} diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java index 3226811fe36e3..84453038cd2c8 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java @@ -39,6 +39,7 @@ import java.time.Duration; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; @@ -317,11 +318,6 @@ PackageTest addHelloAppFileAssociationsVerifier(FileAssociations fa) { return this; } - public PackageTest mutate(Consumer mutator) { - mutator.accept(this); - return this; - } - public PackageTest forTypes(Collection types, Runnable action) { final var oldTypes = Set.of(currentTypes.toArray(PackageType[]::new)); try { @@ -338,11 +334,7 @@ public PackageTest forTypes(PackageType type, Runnable action) { } public PackageTest forTypes(PackageType type, Consumer action) { - return forTypes(List.of(type), action); - } - - public PackageTest forTypes(Collection types, Consumer action) { - return forTypes(types, () -> action.accept(this)); + return forTypes(List.of(type), () -> action.accept(this)); } public PackageTest notForTypes(Collection types, Runnable action) { @@ -356,11 +348,7 @@ public PackageTest notForTypes(PackageType type, Runnable action) { } public PackageTest notForTypes(PackageType type, Consumer action) { - return notForTypes(List.of(type), action); - } - - public PackageTest notForTypes(Collection types, Consumer action) { - return notForTypes(types, () -> action.accept(this)); + return notForTypes(List.of(type), () -> action.accept(this)); } public PackageTest configureHelloApp() { @@ -792,7 +780,7 @@ private void verifyPackageInstalled(JPackageCommand cmd) { LauncherAsServiceVerifier.verify(cmd); } - cmd.runStandardAsserts(); + cmd.assertAppLayout(); installVerifiers.forEach(v -> v.accept(cmd)); } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java index baeeda4e56971..b3f188bb371e0 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java @@ -25,11 +25,10 @@ import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE; import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY; import static java.util.stream.Collectors.toSet; -import static jdk.jpackage.internal.util.function.ThrowingBiFunction.toBiFunction; -import static jdk.jpackage.internal.util.function.ThrowingFunction.toFunction; import static jdk.jpackage.internal.util.function.ThrowingSupplier.toSupplier; import java.io.Closeable; +import java.io.FileOutputStream; import java.io.IOException; import java.io.PrintStream; import java.io.UncheckedIOException; @@ -39,7 +38,6 @@ import java.nio.file.LinkOption; import java.nio.file.Path; import java.nio.file.StandardCopyOption; -import java.nio.file.StandardOpenOption; import java.nio.file.StandardWatchEventKinds; import java.nio.file.WatchEvent; import java.nio.file.WatchKey; @@ -111,7 +109,7 @@ public final class TKit { }).get(); static void withExtraLogStream(ThrowingRunnable action) { - if (state().extraLogStream != null) { + if (extraLogStream != null) { ThrowingRunnable.toRunnable(action).run(); } else { try (PrintStream logStream = openLogStream()) { @@ -121,44 +119,12 @@ static void withExtraLogStream(ThrowingRunnable action) { } static void withExtraLogStream(ThrowingRunnable action, PrintStream logStream) { - withNewState(action, stateBuilder -> { - stateBuilder.extraLogStream(logStream); - }); - } - - public static void withMainLogStream(ThrowingRunnable action, PrintStream logStream) { - withNewState(action, stateBuilder -> { - stateBuilder.mainLogStream(logStream); - }); - } - - public static void withStackTraceStream(ThrowingRunnable action, PrintStream logStream) { - withNewState(action, stateBuilder -> { - stateBuilder.stackTraceStream(logStream); - }); - } - - public static State state() { - return STATE.get(); - } - - public static void state(State v) { - STATE.set(Objects.requireNonNull(v)); - } - - private static void withNewState(ThrowingRunnable action, Consumer stateBuilderMutator) { - Objects.requireNonNull(action); - Objects.requireNonNull(stateBuilderMutator); - - var oldState = state(); - var builder = oldState.buildCopy(); - stateBuilderMutator.accept(builder); - var newState = builder.create(); + var oldExtraLogStream = extraLogStream; try { - state(newState); + extraLogStream = logStream; ThrowingRunnable.toRunnable(action).run(); } finally { - state(oldState); + extraLogStream = oldExtraLogStream; } } @@ -175,25 +141,26 @@ static void runTests(List tests) { static void runTests(List tests, Set modes) { Objects.requireNonNull(tests); Objects.requireNonNull(modes); - if (currentTest() != null) { - throw new IllegalStateException("Unexpected nested Test.run() call"); + if (currentTest != null) { + throw new IllegalStateException( + "Unexpected nested or concurrent Test.run() call"); } withExtraLogStream(() -> { tests.stream().forEach(test -> { - withNewState(() -> { - try { - if (modes.contains(RunTestMode.FAIL_FAST)) { - test.run(); - } else { - ignoreExceptions(test).run(); - } - } finally { - Optional.ofNullable(state().extraLogStream).ifPresent(PrintStream::flush); + currentTest = test; + try { + if (modes.contains(RunTestMode.FAIL_FAST)) { + ThrowingRunnable.toRunnable(test::run).run(); + } else { + ignoreExceptions(test).run(); + } + } finally { + currentTest = null; + if (extraLogStream != null) { + extraLogStream.flush(); } - }, stateBuilder -> { - stateBuilder.currentTest(test); - }); + } }); }); } @@ -250,18 +217,18 @@ static void unbox(Throwable throwable) throws Throwable { } public static Path workDir() { - return currentTest().workDir(); + return currentTest.workDir(); } static String getCurrentDefaultAppName() { // Construct app name from swapping and joining test base name // and test function name. // Say the test name is `FooTest.testBasic`. Then app name would be `BasicFooTest`. - String appNamePrefix = currentTest().functionName(); + String appNamePrefix = currentTest.functionName(); if (appNamePrefix != null && appNamePrefix.startsWith("test")) { appNamePrefix = appNamePrefix.substring("test".length()); } - return Stream.of(appNamePrefix, currentTest().baseName()).filter( + return Stream.of(appNamePrefix, currentTest.baseName()).filter( v -> v != null && !v.isEmpty()).collect(Collectors.joining()); } @@ -289,10 +256,9 @@ private static String addTimestamp(String msg) { static void log(String v) { v = addTimestamp(v); - var state = state(); - state.mainLogStream.println(v); - if (state.extraLogStream != null) { - state.extraLogStream.println(v); + System.out.println(v); + if (extraLogStream != null) { + extraLogStream.println(v); } } @@ -342,13 +308,13 @@ public static void createPropertiesFile(Path propsFilename, } public static void trace(String v) { - if (state().trace) { + if (TRACE) { log("TRACE: " + v); } } private static void traceAssert(String v) { - if (state().traceAsserts) { + if (TRACE_ASSERTS) { log("TRACE: " + v); } } @@ -609,14 +575,10 @@ public static RuntimeException throwSkippedException(String reason) { public static RuntimeException throwSkippedException(RuntimeException ex) { trace("Skip the test: " + ex.getMessage()); - currentTest().notifySkipped(ex); + currentTest.notifySkipped(ex); throw ex; } - public static boolean isSkippedException(Throwable t) { - return JtregSkippedExceptionClass.INSTANCE.isInstance(t); - } - public static Path createRelativePathCopy(final Path file) { Path fileCopy = ThrowingSupplier.toSupplier(() -> { Path localPath = createTempFile(file.getFileName()); @@ -691,9 +653,10 @@ private static void waitForFileCreated(Path fileToWaitFor, Duration timeout) thr } static void printStackTrace(Throwable throwable) { - var state = state(); - Optional.ofNullable(state.extraLogStream).ifPresent(throwable::printStackTrace); - throwable.printStackTrace(state.stackTraceStream); + if (extraLogStream != null) { + throwable.printStackTrace(extraLogStream); + } + throwable.printStackTrace(); } private static String concatMessages(String msg, String msg2) { @@ -704,7 +667,7 @@ private static String concatMessages(String msg, String msg2) { } public static void assertEquals(long expected, long actual, String msg) { - currentTest().notifyAssert(); + currentTest.notifyAssert(); if (expected != actual) { error(concatMessages(String.format( "Expected [%d]. Actual [%d]", expected, actual), @@ -715,7 +678,7 @@ public static void assertEquals(long expected, long actual, String msg) { } public static void assertNotEquals(long expected, long actual, String msg) { - currentTest().notifyAssert(); + currentTest.notifyAssert(); if (expected == actual) { error(concatMessages(String.format("Unexpected [%d] value", actual), msg)); @@ -726,7 +689,7 @@ public static void assertNotEquals(long expected, long actual, String msg) { } public static void assertEquals(boolean expected, boolean actual, String msg) { - currentTest().notifyAssert(); + currentTest.notifyAssert(); if (expected != actual) { error(concatMessages(String.format( "Expected [%s]. Actual [%s]", expected, actual), @@ -737,7 +700,7 @@ public static void assertEquals(boolean expected, boolean actual, String msg) { } public static void assertNotEquals(boolean expected, boolean actual, String msg) { - currentTest().notifyAssert(); + currentTest.notifyAssert(); if (expected == actual) { error(concatMessages(String.format("Unexpected [%s] value", actual), msg)); @@ -749,7 +712,7 @@ public static void assertNotEquals(boolean expected, boolean actual, String msg) public static void assertEquals(Object expected, Object actual, String msg) { - currentTest().notifyAssert(); + currentTest.notifyAssert(); if ((actual != null && !actual.equals(expected)) || (expected != null && !expected.equals(actual))) { error(concatMessages(String.format( @@ -761,7 +724,7 @@ public static void assertEquals(Object expected, Object actual, String msg) { } public static void assertNotEquals(Object expected, Object actual, String msg) { - currentTest().notifyAssert(); + currentTest.notifyAssert(); if ((actual != null && !actual.equals(expected)) || (expected != null && !expected.equals(actual))) { @@ -774,7 +737,7 @@ public static void assertNotEquals(Object expected, Object actual, String msg) { } public static void assertNull(Object value, String msg) { - currentTest().notifyAssert(); + currentTest.notifyAssert(); if (value != null) { error(concatMessages(String.format("Unexpected not null value [%s]", value), msg)); @@ -784,7 +747,7 @@ public static void assertNull(Object value, String msg) { } public static void assertNotNull(Object value, String msg) { - currentTest().notifyAssert(); + currentTest.notifyAssert(); if (value == null) { error(concatMessages("Unexpected null value", msg)); } @@ -801,7 +764,7 @@ public static void assertFalse(boolean actual, String msg) { } public static void assertTrue(boolean actual, String msg, Runnable onFail) { - currentTest().notifyAssert(); + currentTest.notifyAssert(); if (!actual) { if (onFail != null) { onFail.run(); @@ -813,7 +776,7 @@ public static void assertTrue(boolean actual, String msg, Runnable onFail) { } public static void assertFalse(boolean actual, String msg, Runnable onFail) { - currentTest().notifyAssert(); + currentTest.notifyAssert(); if (actual) { if (onFail != null) { onFail.run(); @@ -834,35 +797,6 @@ public static void assertPathExists(Path path, boolean exists) { } } - public static void assertMismatchFileContent(Path a, Path b) { - assertFilesMismatch(a, b, true, Optional.empty()); - } - - public static void assertMismatchFileContent(Path a, Path b, String msg) { - assertFilesMismatch(a, b, true, Optional.of(msg)); - } - - public static void assertSameFileContent(Path a, Path b) { - assertFilesMismatch(a, b, false, Optional.empty()); - } - - public static void assertSameFileContent(Path a, Path b, String msg) { - assertFilesMismatch(a, b, false, Optional.of(msg)); - } - - public static void assertFilesMismatch(Path a, Path b, boolean expectMismatch, Optional msg) { - var mismatch = toBiFunction(Files::mismatch).apply(a, b) != -1; - if (expectMismatch) { - assertTrue(mismatch, msg.orElseGet(() -> { - return String.format("Check the content of [%s] and [%s] files mismatch", a, b); - })); - } else { - assertTrue(!mismatch, msg.orElseGet(() -> { - return String.format("Check the content of [%s] and [%s] files is the same", a, b); - })); - } - } - public static void assertDirectoryNotEmpty(Path path) { assertDirectoryExists(path, Optional.of(false)); } @@ -897,14 +831,7 @@ public static void assertDirectoryExists(Path path) { public static void assertSymbolicLinkExists(Path path) { assertPathExists(path, true); assertTrue(Files.isSymbolicLink(path), String.format - ("Check [%s] is a symbolic link", Objects.requireNonNull(path))); - } - - public static void assertSymbolicLinkTarget(Path symlinkPath, Path expectedTargetPath) { - assertSymbolicLinkExists(symlinkPath); - var targetPath = toFunction(Files::readSymbolicLink).apply(symlinkPath); - assertEquals(expectedTargetPath, targetPath, - String.format("Check the target of the symbolic link [%s]", symlinkPath)); + ("Check [%s] is a symbolic link", path)); } public static void assertFileExists(Path path) { @@ -926,7 +853,7 @@ public static void assertReadableFileExists(Path path) { } public static void assertUnexpected(String msg) { - currentTest().notifyAssert(); + currentTest.notifyAssert(); error(concatMessages("Unexpected", msg)); } @@ -952,7 +879,7 @@ public void match(Path ... expected) { } public void match(Set expected) { - currentTest().notifyAssert(); + currentTest.notifyAssert(); var comm = Comm.compare(content, expected); if (!comm.unique1().isEmpty() && !comm.unique2().isEmpty()) { @@ -979,7 +906,7 @@ public void contains(Path ... expected) { } public void contains(Set expected) { - currentTest().notifyAssert(); + currentTest.notifyAssert(); var comm = Comm.compare(content, expected); if (!comm.unique2().isEmpty()) { @@ -1024,7 +951,7 @@ private static String format(Set paths) { public static void assertStringListEquals(List expected, List actual, String msg) { - currentTest().notifyAssert(); + currentTest.notifyAssert(); traceAssert(concatMessages("assertStringListEquals()", msg)); @@ -1250,13 +1177,12 @@ public static TextStreamVerifier assertTextStream(String what) { } private static PrintStream openLogStream() { - return state().logFile.map(logfile -> { - try { - return Files.newOutputStream(logfile, StandardOpenOption.CREATE, StandardOpenOption.APPEND); - } catch (IOException ex) { - throw new UncheckedIOException(ex); - } - }).map(PrintStream::new).orElse(null); + if (LOG_FILE == null) { + return null; + } + + return ThrowingSupplier.toSupplier(() -> new PrintStream( + new FileOutputStream(LOG_FILE.toFile(), true))).get(); } public record PathSnapshot(List contentHashes) { @@ -1268,8 +1194,8 @@ public PathSnapshot(Path path) { this(hashRecursive(path)); } - public void assertEquals(PathSnapshot other, String msg) { - assertStringListEquals(contentHashes(), other.contentHashes(), msg); + public static void assertEquals(PathSnapshot a, PathSnapshot b, String msg) { + assertStringListEquals(a.contentHashes(), b.contentHashes(), msg); } private static List hashRecursive(Path path) { @@ -1300,6 +1226,15 @@ private static String hashFile(Path path) { } } + private static TestInstance currentTest; + private static PrintStream extraLogStream; + + private static final boolean TRACE; + private static final boolean TRACE_ASSERTS; + + static final boolean VERBOSE_JPACKAGE; + static final boolean VERBOSE_TEST_SETUP; + static String getConfigProperty(String propertyName) { return System.getProperty(getConfigPropertyName(propertyName)); } @@ -1327,19 +1262,38 @@ static Set tokenizeConfigProperty(String propertyName) { return tokens.stream().collect(Collectors.toSet()); } - private static TestInstance currentTest() { - return state().currentTest; - } + static final Path LOG_FILE = Functional.identity(() -> { + String val = getConfigProperty("logfile"); + if (val == null) { + return null; + } + return Path.of(val); + }).get(); - static boolean verboseJPackage() { - return state().verboseJPackage; - } + static { + Set logOptions = tokenizeConfigProperty("suppress-logging"); + if (logOptions == null) { + TRACE = true; + TRACE_ASSERTS = true; + VERBOSE_JPACKAGE = true; + VERBOSE_TEST_SETUP = true; + } else if (logOptions.contains("all")) { + TRACE = false; + TRACE_ASSERTS = false; + VERBOSE_JPACKAGE = false; + VERBOSE_TEST_SETUP = false; + } else { + Predicate> isNonOf = options -> { + return Collections.disjoint(logOptions, options); + }; - static boolean verboseTestSetup() { - return state().verboseTestSetup; + TRACE = isNonOf.test(Set.of("trace", "t")); + TRACE_ASSERTS = isNonOf.test(Set.of("assert", "a")); + VERBOSE_JPACKAGE = isNonOf.test(Set.of("jpackage", "jp")); + VERBOSE_TEST_SETUP = isNonOf.test(Set.of("init", "i")); + } } - private static final class JtregSkippedExceptionClass extends ClassLoader { @SuppressWarnings("unchecked") JtregSkippedExceptionClass() { @@ -1365,159 +1319,4 @@ private static final class JtregSkippedExceptionClass extends ClassLoader { static final Class INSTANCE = new JtregSkippedExceptionClass().clazz; } - - - public static final class State { - - private State( - Optional logFile, - TestInstance currentTest, - PrintStream mainLogStream, - PrintStream stackTraceStream, - PrintStream extraLogStream, - boolean trace, - boolean traceAsserts, - boolean verboseJPackage, - boolean verboseTestSetup) { - - Objects.requireNonNull(logFile); - Objects.requireNonNull(mainLogStream); - Objects.requireNonNull(stackTraceStream); - - this.logFile = logFile; - this.currentTest = currentTest; - this.mainLogStream = mainLogStream; - this.stackTraceStream = stackTraceStream; - this.extraLogStream = extraLogStream; - - this.trace = trace; - this.traceAsserts = traceAsserts; - - this.verboseJPackage = verboseJPackage; - this.verboseTestSetup = verboseTestSetup; - } - - - Builder buildCopy() { - return build().initFrom(this); - } - - static Builder build() { - return new Builder(); - } - - - static final class Builder { - - Builder initDefaults() { - logFile = Optional.ofNullable(getConfigProperty("logfile")).map(Path::of); - currentTest = null; - mainLogStream = System.out; - stackTraceStream = System.err; - extraLogStream = null; - - var logOptions = tokenizeConfigProperty("suppress-logging"); - if (logOptions == null) { - trace = true; - traceAsserts = true; - verboseJPackage = true; - verboseTestSetup = true; - } else if (logOptions.contains("all")) { - trace = false; - traceAsserts = false; - verboseJPackage = false; - verboseTestSetup = false; - } else { - Predicate> isNonOf = options -> { - return Collections.disjoint(logOptions, options); - }; - - trace = isNonOf.test(Set.of("trace", "t")); - traceAsserts = isNonOf.test(Set.of("assert", "a")); - verboseJPackage = isNonOf.test(Set.of("jpackage", "jp")); - verboseTestSetup = isNonOf.test(Set.of("init", "i")); - } - - return this; - } - - Builder initFrom(State state) { - logFile = state.logFile; - currentTest = state.currentTest; - mainLogStream = state.mainLogStream; - stackTraceStream = state.stackTraceStream; - extraLogStream = state.extraLogStream; - - trace = state.trace; - traceAsserts = state.traceAsserts; - - verboseJPackage = state.verboseJPackage; - verboseTestSetup = state.verboseTestSetup; - - return this; - } - - Builder logFile(Optional v) { - logFile = v; - return this; - } - - Builder currentTest(TestInstance v) { - currentTest = v; - return this; - } - - Builder mainLogStream(PrintStream v) { - mainLogStream = v; - return this; - } - - Builder stackTraceStream(PrintStream v) { - stackTraceStream = v; - return this; - } - - Builder extraLogStream(PrintStream v) { - extraLogStream = v; - return this; - } - - State create() { - return new State(logFile, currentTest, mainLogStream, stackTraceStream, extraLogStream, trace, traceAsserts, verboseJPackage, verboseTestSetup); - } - - private Optional logFile; - private TestInstance currentTest; - private PrintStream mainLogStream; - private PrintStream stackTraceStream; - private PrintStream extraLogStream; - - private boolean trace; - private boolean traceAsserts; - - private boolean verboseJPackage; - private boolean verboseTestSetup; - } - - - private final Optional logFile; - private final TestInstance currentTest; - private final PrintStream mainLogStream; - private final PrintStream stackTraceStream; - private final PrintStream extraLogStream; - - private final boolean trace; - private final boolean traceAsserts; - - private final boolean verboseJPackage; - private final boolean verboseTestSetup; - } - - - private static final InheritableThreadLocal STATE = new InheritableThreadLocal<>() { - @Override - protected State initialValue() { - return State.build().initDefaults().create(); - } - }; } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestBuilder.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestBuilder.java index 4009fe2f68723..227c73bc68e4d 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestBuilder.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestBuilder.java @@ -369,7 +369,7 @@ public String getMessage() { } static void trace(String msg) { - if (TKit.verboseTestSetup()) { + if (TKit.VERBOSE_TEST_SETUP) { TKit.log(msg); } } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestMethodSupplier.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestMethodSupplier.java index 80c8b1337905c..36ae81b7db4d6 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestMethodSupplier.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestMethodSupplier.java @@ -409,7 +409,7 @@ private static Object fromString(String value, Class toType) { } private static void trace(String msg) { - if (TKit.verboseTestSetup()) { + if (TKit.VERBOSE_TEST_SETUP) { TKit.log(msg); } } diff --git a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/util/IdentityWrapperTest.java b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/util/IdentityWrapperTest.java deleted file mode 100644 index 471a7cb55a966..0000000000000 --- a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/util/IdentityWrapperTest.java +++ /dev/null @@ -1,157 +0,0 @@ -/* - * 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 jdk.jpackage.internal.util; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertNotEquals; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; - -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; -import org.junit.jupiter.api.Test; - - -public class IdentityWrapperTest { - - @Test - public void test_null() { - assertThrows(NullPointerException.class, () -> identityOf(null)); - } - - @Test - public void test_equals() { - var obj = new TestRecord(10); - assertEquals(identityOf(obj), identityOf(obj)); - } - - @Test - public void test_not_equals() { - var identity = identityOf(new TestRecord(10)); - var identity2 = identityOf(new TestRecord(10)); - assertNotEquals(identity, identity2); - assertEquals(identity.value(), identity2.value()); - } - - @Test - public void test_Foo() { - var foo = new Foo(10); - assertFalse(foo.accessed()); - - foo.hashCode(); - assertTrue(foo.accessed()); - assertTrue(foo.hashCodeCalled()); - assertFalse(foo.equalsCalled()); - - foo = new Foo(1); - foo.equals(null); - assertTrue(foo.accessed()); - assertFalse(foo.hashCodeCalled()); - assertTrue(foo.equalsCalled()); - } - - @Test - public void test_wrappedValue_not_accessed() { - var identity = identityOf(new Foo(10)); - var identity2 = identityOf(new Foo(10)); - assertNotEquals(identity, identity2); - - assertFalse(identity.value().accessed()); - assertFalse(identity2.value().accessed()); - - assertEquals(identity.value(), identity2.value()); - assertEquals(identity2.value(), identity.value()); - - assertTrue(identity.value().accessed()); - assertTrue(identity2.value().accessed()); - } - - @Test - public void test_wrappedValue_not_accessed_in_set() { - var identitySet = Set.of(identityOf(new Foo(10)), identityOf(new Foo(10)), identityOf(new Foo(10))); - assertEquals(3, identitySet.size()); - - var valueSet = identitySet.stream().peek(identity -> { - assertFalse(identity.value().accessed()); - }).map(IdentityWrapper::value).collect(Collectors.toSet()); - - assertEquals(1, valueSet.size()); - } - - private static IdentityWrapper identityOf(T obj) { - return new IdentityWrapper<>(obj); - } - - private record TestRecord(int v) {} - - private final static class Foo { - - Foo(int v) { - this.v = v; - } - - @Override - public int hashCode() { - try { - return Objects.hash(v); - } finally { - hashCodeCalled = true; - } - } - - @Override - public boolean equals(Object obj) { - try { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Foo other = (Foo) obj; - return v == other.v; - } finally { - equalsCalled = true; - } - } - - boolean equalsCalled() { - return equalsCalled; - } - - boolean hashCodeCalled() { - return hashCodeCalled; - } - - boolean accessed() { - return equalsCalled() || hashCodeCalled(); - } - - private final int v; - private boolean equalsCalled; - private boolean hashCodeCalled; - } -} diff --git a/test/jdk/tools/jpackage/junit/tools/jdk/jpackage/test/JUnitUtils.java b/test/jdk/tools/jpackage/junit/tools/jdk/jpackage/test/JUnitUtils.java deleted file mode 100644 index c91b178cb108b..0000000000000 --- a/test/jdk/tools/jpackage/junit/tools/jdk/jpackage/test/JUnitUtils.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * 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 jdk.jpackage.test; - -import java.util.Map; -import java.util.Objects; -import org.junit.jupiter.api.Assertions; - - -public final class JUnitUtils { - - /** - * Convenience adapter for {@link Assertions#assertArrayEquals(byte[], byte[])}, - * {@link Assertions#assertArrayEquals(int[], int[])}, - * {@link Assertions#assertArrayEquals(Object[], Object[])}, etc. methods. - * - * @param expected the expected array to test for equality - * @param actual the actual array to test for equality - */ - public static void assertArrayEquals(Object expected, Object actual) { - ARRAY_ASSERTERS.getOrDefault(expected.getClass().componentType(), OBJECT_ARRAY_ASSERTER).acceptUnchecked(expected, actual); - } - - /** - * Converts the given exception object to a property map. - *

    - * Values returned by public getters are added to the map. Names of getters are - * the keys in the returned map. The values are property map representations of - * the objects returned by the getters. Only {@link Throwable#getMessage()} and - * {@link Throwable#getCause()} getters are picked for the property map by - * default. If the exception class has additional getters, they will be added to - * the map. {@code null} is permitted. - * - * @param ex the exception to convert into a property map - * @return the property map view of the given exception object - */ - public static Map exceptionAsPropertyMap(Exception ex) { - return EXCEPTION_OM.toMap(ex); - } - - - public static final class ExceptionPattern { - - public ExceptionPattern() { - } - - public boolean match(Exception ex) { - Objects.requireNonNull(ex); - - if (expectedType != null && !expectedType.isInstance(ex)) { - return false; - } - - if (expectedMessage != null && !expectedMessage.equals(ex.getMessage())) { - return false; - } - - if (expectedCauseType != null && !expectedCauseType.isInstance(ex.getCause())) { - return false; - } - - return true; - } - - public ExceptionPattern hasMessage(String v) { - expectedMessage = v; - return this; - } - - public ExceptionPattern isInstanceOf(Class v) { - expectedType = v; - return this; - } - - public ExceptionPattern isCauseInstanceOf(Class v) { - expectedCauseType = v; - return this; - } - - public ExceptionPattern hasCause(boolean v) { - return isCauseInstanceOf(v ? Exception.class : null); - } - - public ExceptionPattern hasCause() { - return hasCause(true); - } - - private String expectedMessage; - private Class expectedType; - private Class expectedCauseType; - } - - - @FunctionalInterface - private interface ArrayEqualsAsserter { - void accept(T expected, T actual); - - @SuppressWarnings("unchecked") - default void acceptUnchecked(Object expected, Object actual) { - accept((T)expected, (T)actual); - } - } - - - private static final Map, ArrayEqualsAsserter> ARRAY_ASSERTERS = Map.of( - boolean.class, (ArrayEqualsAsserter)Assertions::assertArrayEquals, - byte.class, (ArrayEqualsAsserter)Assertions::assertArrayEquals, - char.class, (ArrayEqualsAsserter)Assertions::assertArrayEquals, - double.class, (ArrayEqualsAsserter)Assertions::assertArrayEquals, - float.class, (ArrayEqualsAsserter)Assertions::assertArrayEquals, - int.class, (ArrayEqualsAsserter)Assertions::assertArrayEquals, - long.class, (ArrayEqualsAsserter)Assertions::assertArrayEquals, - short.class, (ArrayEqualsAsserter)Assertions::assertArrayEquals - ); - - private static final ArrayEqualsAsserter OBJECT_ARRAY_ASSERTER = Assertions::assertArrayEquals; - - private static final ObjectMapper EXCEPTION_OM = ObjectMapper.standard().create(); -} diff --git a/test/jdk/tools/jpackage/linux/ShortcutHintTest.java b/test/jdk/tools/jpackage/linux/ShortcutHintTest.java index 8d373cb2b86dc..4d3b33bcd6b58 100644 --- a/test/jdk/tools/jpackage/linux/ShortcutHintTest.java +++ b/test/jdk/tools/jpackage/linux/ShortcutHintTest.java @@ -164,7 +164,7 @@ public static void testDesktopFileFromResourceDir() throws IOException { "Exec=APPLICATION_LAUNCHER", "Terminal=false", "Type=Application", - "Comment=APPLICATION_DESCRIPTION", + "Comment=", "Icon=APPLICATION_ICON", "Categories=DEPLOY_BUNDLE_CATEGORY", expectedVersionString diff --git a/test/jdk/tools/jpackage/macosx/CustomInfoPListTest.java b/test/jdk/tools/jpackage/macosx/CustomInfoPListTest.java index d91f4e3504b7b..f8e606d77e8a0 100644 --- a/test/jdk/tools/jpackage/macosx/CustomInfoPListTest.java +++ b/test/jdk/tools/jpackage/macosx/CustomInfoPListTest.java @@ -21,7 +21,6 @@ * questions. */ -import static java.util.Collections.unmodifiableSortedSet; import static java.util.Map.entry; import static jdk.jpackage.internal.util.PListWriter.writeDict; import static jdk.jpackage.internal.util.PListWriter.writePList; @@ -41,7 +40,6 @@ import java.util.Map; import java.util.Objects; import java.util.Set; -import java.util.TreeSet; import java.util.function.BiConsumer; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -144,12 +142,12 @@ public record TestConfig(Set customPLists) { if (customPLists.isEmpty()) { throw new IllegalArgumentException(); } - customPLists = unmodifiableSortedSet(new TreeSet<>(customPLists)); } @Override public String toString() { return customPLists.stream() + .sorted(Comparator.comparing(CustomPListType::role)) .map(CustomPListType::toString) .collect(Collectors.joining("+")); } @@ -157,12 +155,12 @@ public String toString() { JPackageCommand init(JPackageCommand cmd) throws IOException { if (customPLists.contains(CustomPListType.APP_WITH_FA)) { final Path propFile = TKit.createTempFile("fa.properties"); - final var props = List.of( + var map = Map.ofEntries( entry("mime-type", "application/x-jpackage-foo"), entry("extension", "foo"), entry("description", "bar") ); - TKit.createPropertiesFile(propFile, props); + TKit.createPropertiesFile(propFile, map); cmd.setArgumentValue("--file-associations", propFile); } diff --git a/test/jdk/tools/jpackage/macosx/EntitlementsTest.java b/test/jdk/tools/jpackage/macosx/EntitlementsTest.java deleted file mode 100644 index aa5879e0c619e..0000000000000 --- a/test/jdk/tools/jpackage/macosx/EntitlementsTest.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * 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. - */ - -import static jdk.jpackage.internal.util.PListWriter.writeBoolean; -import static jdk.jpackage.internal.util.PListWriter.writeDict; -import static jdk.jpackage.internal.util.PListWriter.writePList; -import static jdk.jpackage.internal.util.XmlUtils.createXml; -import static jdk.jpackage.internal.util.XmlUtils.toXmlConsumer; -import static jdk.jpackage.internal.util.function.ThrowingConsumer.toConsumer; - -import java.io.IOException; -import java.nio.file.Path; -import java.util.function.Consumer; -import java.util.stream.Stream; -import jdk.jpackage.internal.util.function.ThrowingConsumer; -import jdk.jpackage.test.AdditionalLauncher; -import jdk.jpackage.test.Annotations.Parameter; -import jdk.jpackage.test.Annotations.Test; -import jdk.jpackage.test.JPackageCommand; -import jdk.jpackage.test.MacHelper; -import jdk.jpackage.test.MacHelper.SignKeyOption; -import jdk.jpackage.test.MacSign; -import jdk.jpackage.test.TKit; - -/* - * Test generates signed app-image with custom entitlements file from the - * "--mac-entitlements" parameter and the resource directory. Following cases - * are covered: - * - Custom entitlements file in the resource directory. - * - Custom entitlements file specified with the "--mac-entitlements" parameter. - * - Custom entitlements file in the resource directory and specified with the - * "--mac-entitlements" parameter. - */ - -/* - * @test - * @summary jpackage with --type app-image "--mac-entitlements" parameter - * @library /test/jdk/tools/jpackage/helpers - * @library base - * @build SigningBase - * @build jdk.jpackage.test.* - * @build EntitlementsTest - * @requires (jpackage.test.MacSignTests == "run") - * @run main/othervm/timeout=720 -Xmx512m jdk.jpackage.test.Main - * --jpt-run=EntitlementsTest - * --jpt-before-run=SigningBase.verifySignTestEnvReady - */ -public class EntitlementsTest { - - private static void createEntitlementsFile(Path file, boolean microphone) throws IOException { - createXml(file, xml -> { - writePList(xml, toXmlConsumer(() -> { - writeDict(xml, toXmlConsumer(() -> { - writeBoolean(xml, "com.apple.security.cs.allow-jit", true); - writeBoolean(xml, "com.apple.security.cs.allow-unsigned-executable-memory", true); - writeBoolean(xml, "com.apple.security.cs.disable-library-validation", true); - writeBoolean(xml, "com.apple.security.cs.allow-dyld-environment-variables", true); - writeBoolean(xml, "com.apple.security.cs.debugger", true); - writeBoolean(xml, "com.apple.security.device.audio-input", true); - writeBoolean(xml, "com.apple.security.device.microphone", microphone); - })); - })); - }); - } - - public enum EntitlementsSource implements Consumer { - CMDLINE(cmd -> { - var macEntitlementsFile = TKit.createTempFile("foo.plist"); - createEntitlementsFile(macEntitlementsFile, true); - cmd.addArguments("--mac-entitlements", macEntitlementsFile); - }), - RESOURCE_DIR(cmd -> { - if (!cmd.hasArgument("--resource-dir")) { - cmd.setArgumentValue("--resource-dir", TKit.createTempDirectory("resources")); - } - - var resourcesDir = Path.of(cmd.getArgumentValue("--resource-dir")); - createEntitlementsFile(resourcesDir.resolve(cmd.name() + ".entitlements"), false); - }), - ; - - EntitlementsSource(ThrowingConsumer initializer) { - this.initializer = toConsumer(initializer); - } - - @Override - public void accept(JPackageCommand cmd) { - initializer.accept(cmd); - } - - private final Consumer initializer; - } - - @Test - @Parameter({"CMDLINE"}) - @Parameter({"RESOURCE_DIR"}) - @Parameter({"CMDLINE", "RESOURCE_DIR"}) - public static void test(EntitlementsSource... entitlementsSources) { - MacSign.withKeychain(toConsumer(keychain -> { - test(keychain, Stream.of(entitlementsSources)); - }), SigningBase.StandardKeychain.MAIN.keychain()); - } - - @Test - @Parameter({"CMDLINE"}) - @Parameter({"RESOURCE_DIR"}) - @Parameter({"CMDLINE", "RESOURCE_DIR"}) - public static void testAppStore(EntitlementsSource... entitlementsSources) { - MacSign.withKeychain(toConsumer(keychain -> { - test(keychain, Stream.concat(Stream.of(cmd -> { - cmd.addArguments("--mac-app-store"); - // Ignore externally supplied runtime as it may have the "bin" - // directory that will cause jpackage to bail out. - cmd.ignoreDefaultRuntime(true); - }), Stream.of(entitlementsSources))); - }), SigningBase.StandardKeychain.MAIN.keychain()); - } - - private static void test(MacSign.ResolvedKeychain keychain, Stream> mutators) { - - var cmd = JPackageCommand.helloAppImage(); - - cmd.mutate(MacHelper.useKeychain(keychain)).mutate(new SignKeyOption( - SignKeyOption.Type.SIGN_KEY_IDENTITY, - SigningBase.StandardCertificateRequest.CODESIGN.spec() - )::addTo); - - cmd.mutate(new AdditionalLauncher("x")::applyTo); - - mutators.forEach(cmd::mutate); - - cmd.executeAndAssertHelloAppImageCreated(); - } -} diff --git a/test/jdk/tools/jpackage/macosx/MacFileAssociationsTest.java b/test/jdk/tools/jpackage/macosx/MacFileAssociationsTest.java index ab7a23ec89a08..3277b56ab46cc 100644 --- a/test/jdk/tools/jpackage/macosx/MacFileAssociationsTest.java +++ b/test/jdk/tools/jpackage/macosx/MacFileAssociationsTest.java @@ -32,7 +32,6 @@ import java.nio.file.Path; import java.util.Comparator; -import java.util.List; import java.util.Map; import java.util.function.Function; import java.util.stream.Stream; @@ -62,7 +61,7 @@ public class MacFileAssociationsTest { @Test public static void test() throws Exception { final Path propFile = TKit.createTempFile("fa.properties"); - final var props = List.of( + Map map = Map.ofEntries( entry("mime-type", "application/x-jpackage-foo"), entry("extension", "foo"), entry("description", "bar"), @@ -74,7 +73,7 @@ public static void test() throws Exception { entry("mac.UISupportsDocumentBrowser", "false"), entry("mac.NSExportableTypes", "public.png, public.jpg"), entry("mac.UTTypeConformsTo", "public.image, public.data")); - TKit.createPropertiesFile(propFile, props); + TKit.createPropertiesFile(propFile, map); final var cmd = JPackageCommand.helloAppImage().setFakeRuntime(); cmd.addArguments("--file-associations", propFile); diff --git a/test/jdk/tools/jpackage/macosx/MacSignTest.java b/test/jdk/tools/jpackage/macosx/MacSignTest.java index f5f8b3825ccae..b6f3f91ff585e 100644 --- a/test/jdk/tools/jpackage/macosx/MacSignTest.java +++ b/test/jdk/tools/jpackage/macosx/MacSignTest.java @@ -70,14 +70,14 @@ public static void testAppContentWarning() throws IOException { final List expectedStrings = new ArrayList<>(); expectedStrings.add(JPackageStringBundle.MAIN.cannedFormattedString("message.codesign.failed.reason.app.content")); - expectedStrings.add(JPackageStringBundle.MAIN.cannedFormattedString("error.tool.failed.with.output", "codesign")); - final var xcodeWarning = JPackageStringBundle.MAIN.cannedFormattedString("message.codesign.failed.reason.xcode.tools"); if (!MacHelper.isXcodeDevToolsInstalled()) { expectedStrings.add(xcodeWarning); } - MacSign.withKeychain(keychain -> { + final var keychain = SigningBase.StandardKeychain.EXPIRED.spec().keychain(); + + MacSign.Keychain.withAddedKeychains(List.of(keychain), () -> { // --app-content and --type app-image // Expect `message.codesign.failed.reason.app.content` message in the log. // This is not a fatal error, just a warning. @@ -86,6 +86,8 @@ public static void testAppContentWarning() throws IOException { .ignoreDefaultVerbose(true) .validateOutput(expectedStrings.toArray(CannedFormattedString[]::new)) .addArguments("--app-content", appContent) + .addArguments("--mac-sign") + .addArguments("--mac-signing-keychain", keychain.name()) .addArguments("--mac-app-image-sign-identity", SigningBase.StandardCertificateRequest.CODESIGN.spec().name()); if (MacHelper.isXcodeDevToolsInstalled()) { @@ -93,36 +95,8 @@ public static void testAppContentWarning() throws IOException { cmd.validateOutput(TKit.assertTextStream(xcodeWarning.getValue()).negate()); } - MacHelper.useKeychain(cmd, keychain).execute(1); - }, MacSign.Keychain.UsageBuilder::addToSearchList, SigningBase.StandardKeychain.MAIN.keychain()); - } - - @Test - public static void testCodesignUnspecifiedFailure() throws IOException { - - var appImageCmd = JPackageCommand.helloAppImage().setFakeRuntime(); - - appImageCmd.executeIgnoreExitCode().assertExitCodeIsZero(); - - // This test expects jpackage to respond in a specific way on a codesign failure. - // The simplest option to trigger codesign failure is to request the signing of an invalid bundle. - // Create app content directory with the name known to fail signing. - final var appContent = appImageCmd.appLayout().contentDirectory().resolve("foo.1"); - Files.createDirectory(appContent); - Files.createFile(appContent.resolve("file")); - - final List expectedStrings = new ArrayList<>(); - expectedStrings.add(JPackageStringBundle.MAIN.cannedFormattedString("error.tool.failed.with.output", "codesign")); - - MacSign.withKeychain(keychain -> { - final var cmd = new JPackageCommand().setPackageType(PackageType.IMAGE) - .ignoreDefaultVerbose(true) - .validateOutput(expectedStrings.toArray(CannedFormattedString[]::new)) - .addArguments("--app-image", appImageCmd.outputBundle()) - .addArguments("--mac-app-image-sign-identity", SigningBase.StandardCertificateRequest.CODESIGN.spec().name()); - - MacHelper.useKeychain(cmd, keychain).execute(1); - }, MacSign.Keychain.UsageBuilder::addToSearchList, SigningBase.StandardKeychain.MAIN.keychain()); + cmd.execute(1); + }); } @Test @@ -142,16 +116,20 @@ public static void testCodesignUnspecifiedFailure() throws IOException { @Parameter({"MAC_PKG", "EXPIRED_CODESIGN_SIGN_IDENTITY", "GOOD_PKG_SIGN_IDENTITY"}) public static void testExpiredCertificate(PackageType type, SignOption... options) { - MacSign.withKeychain(keychain -> { - final var cmd = MacHelper.useKeychain(JPackageCommand.helloAppImage(), keychain) + final var keychain = SigningBase.StandardKeychain.EXPIRED.spec().keychain(); + + MacSign.Keychain.withAddedKeychains(List.of(keychain), () -> { + final var cmd = JPackageCommand.helloAppImage() .ignoreDefaultVerbose(true) + .addArguments("--mac-sign") + .addArguments("--mac-signing-keychain", keychain.name()) .addArguments(Stream.of(options).map(SignOption::args).flatMap(List::stream).toList()) .setPackageType(type); SignOption.configureOutputValidation(cmd, Stream.of(options).filter(SignOption::expired).toList(), opt -> { return JPackageStringBundle.MAIN.cannedFormattedString("error.certificate.expired", opt.identityName()); }).execute(1); - }, MacSign.Keychain.UsageBuilder::addToSearchList, SigningBase.StandardKeychain.EXPIRED.keychain()); + }); } @Test @@ -170,31 +148,39 @@ public static void testExpiredCertificate(PackageType type, SignOption... option @Parameter({"MAC_PKG", "1", "GOOD_PKG_SIGN_IDENTITY"}) public static void testMultipleCertificates(PackageType type, int jpackageExitCode, SignOption... options) { - MacSign.withKeychain(keychain -> { - final var cmd = MacHelper.useKeychain(JPackageCommand.helloAppImage(), keychain) + final var keychain = SigningBase.StandardKeychain.DUPLICATE.spec().keychain(); + + MacSign.Keychain.withAddedKeychains(List.of(keychain), () -> { + final var cmd = JPackageCommand.helloAppImage() .ignoreDefaultVerbose(true) + .addArguments("--mac-sign") + .addArguments("--mac-signing-keychain", keychain.name()) .addArguments(Stream.of(options).map(SignOption::args).flatMap(List::stream).toList()) .setPackageType(type); SignOption.configureOutputValidation(cmd, List.of(options), opt -> { return JPackageStringBundle.MAIN.cannedFormattedString("error.multiple.certs.found", opt.identityName(), keychain.name()); }).execute(jpackageExitCode); - }, MacSign.Keychain.UsageBuilder::addToSearchList, SigningBase.StandardKeychain.DUPLICATE.keychain()); + }); } @Test @ParameterSupplier public static void testSelectSigningIdentity(String signingKeyUserName, CertificateRequest certRequest) { - MacSign.withKeychain(keychain -> { - final var cmd = MacHelper.useKeychain(JPackageCommand.helloAppImage(), keychain) + final var keychain = SigningBase.StandardKeychain.MAIN.spec().keychain(); + + MacSign.Keychain.withAddedKeychains(List.of(keychain), () -> { + final var cmd = JPackageCommand.helloAppImage() .setFakeRuntime() + .addArguments("--mac-sign") + .addArguments("--mac-signing-keychain", keychain.name()) .addArguments("--mac-signing-key-user-name", signingKeyUserName); cmd.executeAndAssertHelloAppImageCreated(); MacSignVerify.assertSigned(cmd.outputBundle(), certRequest); - }, MacSign.Keychain.UsageBuilder::addToSearchList, SigningBase.StandardKeychain.MAIN.keychain()); + }); } public static Collection testSelectSigningIdentity() { diff --git a/test/jdk/tools/jpackage/macosx/SigningAppImageTest.java b/test/jdk/tools/jpackage/macosx/SigningAppImageTest.java index 37ba8a6c299ac..e93e659408fef 100644 --- a/test/jdk/tools/jpackage/macosx/SigningAppImageTest.java +++ b/test/jdk/tools/jpackage/macosx/SigningAppImageTest.java @@ -21,14 +21,12 @@ * questions. */ -import static jdk.jpackage.internal.util.function.ThrowingConsumer.toConsumer; - import java.nio.file.Path; -import jdk.jpackage.test.AdditionalLauncher; -import jdk.jpackage.test.Annotations.Parameter; -import jdk.jpackage.test.Annotations.Test; + import jdk.jpackage.test.JPackageCommand; -import jdk.jpackage.test.MacSign; +import jdk.jpackage.test.Annotations.Test; +import jdk.jpackage.test.Annotations.Parameter; +import jdk.jpackage.test.AdditionalLauncher; /** * Tests generation of app image with --mac-sign and related arguments. Test will @@ -70,19 +68,13 @@ public class SigningAppImageTest { // Unsigned @Parameter({"false", "true", "INVALID_INDEX"}) public void test(boolean doSign, boolean signingKey, SigningBase.CertIndex certEnum) throws Exception { - MacSign.withKeychain(toConsumer(keychain -> { - test(keychain, doSign, signingKey, certEnum); - }), SigningBase.StandardKeychain.MAIN.keychain()); - } - - private void test(MacSign.ResolvedKeychain keychain, boolean doSign, boolean signingKey, SigningBase.CertIndex certEnum) throws Exception { final var certIndex = certEnum.value(); JPackageCommand cmd = JPackageCommand.helloAppImage(); if (doSign) { cmd.addArguments("--mac-sign", "--mac-signing-keychain", - keychain.name()); + SigningBase.getKeyChain()); if (signingKey) { cmd.addArguments("--mac-signing-key-user-name", SigningBase.getDevName(certIndex)); diff --git a/test/jdk/tools/jpackage/macosx/SigningAppImageTwoStepsTest.java b/test/jdk/tools/jpackage/macosx/SigningAppImageTwoStepsTest.java index 906734e6a9cb2..94199b31434f7 100644 --- a/test/jdk/tools/jpackage/macosx/SigningAppImageTwoStepsTest.java +++ b/test/jdk/tools/jpackage/macosx/SigningAppImageTwoStepsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,16 +21,14 @@ * questions. */ -import static jdk.jpackage.internal.util.function.ThrowingConsumer.toConsumer; - import java.nio.file.Path; -import jdk.jpackage.test.AdditionalLauncher; -import jdk.jpackage.test.Annotations.Parameter; -import jdk.jpackage.test.Annotations.Test; + import jdk.jpackage.test.JPackageCommand; -import jdk.jpackage.test.MacSign; -import jdk.jpackage.test.PackageType; import jdk.jpackage.test.TKit; +import jdk.jpackage.test.PackageType; +import jdk.jpackage.test.Annotations.Test; +import jdk.jpackage.test.Annotations.Parameter; +import jdk.jpackage.test.AdditionalLauncher; /** * Tests generation of app image and then signs generated app image with --mac-sign @@ -69,12 +67,6 @@ public class SigningAppImageTwoStepsTest { // Unsigned @Parameter({"false", "true"}) public void test(boolean signAppImage, boolean signingKey) throws Exception { - MacSign.withKeychain(toConsumer(keychain -> { - test(keychain, signAppImage, signingKey); - }), SigningBase.StandardKeychain.MAIN.keychain()); - } - - private static void test(MacSign.ResolvedKeychain keychain, boolean signAppImage, boolean signingKey) throws Exception { Path appimageOutput = TKit.createTempDirectory("appimage"); @@ -86,7 +78,7 @@ private static void test(MacSign.ResolvedKeychain keychain, boolean signAppImage if (signAppImage) { appImageCmd.addArguments("--mac-sign", "--mac-signing-keychain", - keychain.name()); + SigningBase.getKeyChain()); if (signingKey) { appImageCmd.addArguments("--mac-signing-key-user-name", SigningBase.getDevName(SigningBase.DEFAULT_INDEX)); @@ -111,7 +103,7 @@ private static void test(MacSign.ResolvedKeychain keychain, boolean signAppImage cmd.setPackageType(PackageType.IMAGE) .addArguments("--app-image", appImageCmd.outputBundle().toAbsolutePath()) .addArguments("--mac-sign") - .addArguments("--mac-signing-keychain", keychain.name()); + .addArguments("--mac-signing-keychain", SigningBase.getKeyChain()); if (signingKey) { cmd.addArguments("--mac-signing-key-user-name", SigningBase.getDevName(SigningBase.DEFAULT_INDEX)); diff --git a/test/jdk/tools/jpackage/macosx/SigningPackageFromTwoStepAppImageTest.java b/test/jdk/tools/jpackage/macosx/SigningPackageFromTwoStepAppImageTest.java index 6db1cb2faabb4..d25d9a7fa8146 100644 --- a/test/jdk/tools/jpackage/macosx/SigningPackageFromTwoStepAppImageTest.java +++ b/test/jdk/tools/jpackage/macosx/SigningPackageFromTwoStepAppImageTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,18 +21,15 @@ * questions. */ -import static jdk.jpackage.internal.util.function.ThrowingConsumer.toConsumer; - import java.nio.file.Path; -import jdk.jpackage.test.Annotations.Parameter; -import jdk.jpackage.test.Annotations.Test; import jdk.jpackage.test.ApplicationLayout; import jdk.jpackage.test.JPackageCommand; -import jdk.jpackage.test.MacHelper; -import jdk.jpackage.test.MacSign; +import jdk.jpackage.test.TKit; import jdk.jpackage.test.PackageTest; import jdk.jpackage.test.PackageType; -import jdk.jpackage.test.TKit; +import jdk.jpackage.test.MacHelper; +import jdk.jpackage.test.Annotations.Test; +import jdk.jpackage.test.Annotations.Parameter; /** * Tests generation of dmg and pkg from signed predefined app image which was @@ -105,12 +102,6 @@ private static void verifyAppImageInDMG(JPackageCommand cmd) { // Unsigned @Parameter({"false", "true"}) public void test(boolean signAppImage, boolean signingKey) throws Exception { - MacSign.withKeychain(toConsumer(keychain -> { - test(keychain, signAppImage, signingKey); - }), SigningBase.StandardKeychain.MAIN.keychain()); - } - - private void test(MacSign.ResolvedKeychain keychain, boolean signAppImage, boolean signingKey) throws Exception { Path appimageOutput = TKit.createTempDirectory("appimage"); @@ -121,7 +112,7 @@ private void test(MacSign.ResolvedKeychain keychain, boolean signAppImage, boole .setArgumentValue("--dest", appimageOutput); if (signAppImage) { appImageCmd.addArguments("--mac-sign", - "--mac-signing-keychain", keychain.name()); + "--mac-signing-keychain", SigningBase.getKeyChain()); if (signingKey) { appImageCmd.addArguments("--mac-signing-key-user-name", SigningBase.getDevName(SigningBase.DEFAULT_INDEX)); @@ -142,7 +133,7 @@ private void test(MacSign.ResolvedKeychain keychain, boolean signAppImage, boole appImageSignedCmd.setPackageType(PackageType.IMAGE) .addArguments("--app-image", appImageCmd.outputBundle().toAbsolutePath()) .addArguments("--mac-sign") - .addArguments("--mac-signing-keychain", keychain.name()); + .addArguments("--mac-signing-keychain", SigningBase.getKeyChain()); if (signingKey) { appImageSignedCmd.addArguments("--mac-signing-key-user-name", SigningBase.getDevName(SigningBase.DEFAULT_INDEX)); @@ -163,7 +154,7 @@ private void test(MacSign.ResolvedKeychain keychain, boolean signAppImage, boole if (signAppImage) { cmd.addArguments("--mac-sign", "--mac-signing-keychain", - keychain.name()); + SigningBase.getKeyChain()); if (signingKey) { cmd.addArguments("--mac-signing-key-user-name", SigningBase.getDevName(SigningBase.DEFAULT_INDEX)); diff --git a/test/jdk/tools/jpackage/macosx/SigningPackageTest.java b/test/jdk/tools/jpackage/macosx/SigningPackageTest.java index b1e9155dacbcf..2c2f5c3bb0f0c 100644 --- a/test/jdk/tools/jpackage/macosx/SigningPackageTest.java +++ b/test/jdk/tools/jpackage/macosx/SigningPackageTest.java @@ -21,17 +21,14 @@ * questions. */ -import static jdk.jpackage.internal.util.function.ThrowingConsumer.toConsumer; - import java.nio.file.Path; -import jdk.jpackage.test.Annotations.Parameter; -import jdk.jpackage.test.Annotations.Test; import jdk.jpackage.test.ApplicationLayout; import jdk.jpackage.test.JPackageCommand; -import jdk.jpackage.test.MacHelper; -import jdk.jpackage.test.MacSign; import jdk.jpackage.test.PackageTest; import jdk.jpackage.test.PackageType; +import jdk.jpackage.test.MacHelper; +import jdk.jpackage.test.Annotations.Test; +import jdk.jpackage.test.Annotations.Parameter; /** * Tests generation of dmg and pkg with --mac-sign and related arguments. @@ -147,12 +144,6 @@ private static int getCertIndex(JPackageCommand cmd) { // Signing-indentity, but sign pkg only and UNICODE certificate @Parameter({"false", "false", "true", "UNICODE_INDEX"}) public static void test(boolean signingKey, boolean signAppImage, boolean signPKG, SigningBase.CertIndex certEnum) throws Exception { - MacSign.withKeychain(toConsumer(keychain -> { - test(keychain, signingKey, signAppImage, signPKG, certEnum); - }), SigningBase.StandardKeychain.MAIN.keychain()); - } - - private static void test(MacSign.ResolvedKeychain keychain, boolean signingKey, boolean signAppImage, boolean signPKG, SigningBase.CertIndex certEnum) throws Exception { final var certIndex = certEnum.value(); new PackageTest() @@ -160,7 +151,7 @@ private static void test(MacSign.ResolvedKeychain keychain, boolean signingKey, .forTypes(PackageType.MAC) .addInitializer(cmd -> { cmd.addArguments("--mac-sign", - "--mac-signing-keychain", keychain.name()); + "--mac-signing-keychain", SigningBase.getKeyChain()); if (signingKey) { cmd.addArguments("--mac-signing-key-user-name", SigningBase.getDevName(certIndex)); diff --git a/test/jdk/tools/jpackage/macosx/SigningPackageTwoStepTest.java b/test/jdk/tools/jpackage/macosx/SigningPackageTwoStepTest.java index 16cf616cfd377..3522d8d43e527 100644 --- a/test/jdk/tools/jpackage/macosx/SigningPackageTwoStepTest.java +++ b/test/jdk/tools/jpackage/macosx/SigningPackageTwoStepTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,39 +21,31 @@ * questions. */ -import static jdk.jpackage.internal.util.function.ThrowingConsumer.toConsumer; - import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.SortedMap; -import java.util.TreeMap; -import java.util.stream.Stream; -import jdk.jpackage.test.Annotations.ParameterSupplier; -import jdk.jpackage.test.Annotations.Test; +import jdk.jpackage.test.ApplicationLayout; import jdk.jpackage.test.JPackageCommand; -import jdk.jpackage.test.JPackageStringBundle; -import jdk.jpackage.test.MacHelper; -import jdk.jpackage.test.MacHelper.SignKeyOption; -import jdk.jpackage.test.MacSign; -import jdk.jpackage.test.MacSignVerify; -import jdk.jpackage.test.PackageFile; +import jdk.jpackage.test.TKit; import jdk.jpackage.test.PackageTest; import jdk.jpackage.test.PackageType; -import jdk.jpackage.test.TKit; +import jdk.jpackage.test.MacHelper; +import jdk.jpackage.test.Annotations.Test; +import jdk.jpackage.test.Annotations.Parameter; /** - * Tests packaging of a signed/unsigned predefined app image into a - * signed/unsigned .pkg or .dmg package. - * - *

    - * Prerequisites: A keychain with self-signed certificates as specified in - * {@link SigningBase.StandardKeychain#MAIN}. + * Note: Testing unsgined app image is done to verify support for per-user + * configuration by checking for PackageFile. + * Tests generation of dmg and pkg from signed or unsigned predefined app image. + * Test will generate pkg and verifies its signature. It verifies that dmg + * is not signed, but app image inside dmg is signed or unsigned. This test + * requires that the machine is configured with test certificate for + * "Developer ID Installer: jpackage.openjdk.java.net" in + * jpackagerTest keychain with + * always allowed access to this keychain for user which runs test. + * note: + * "jpackage.openjdk.java.net" can be over-ridden by system property + * "jpackage.mac.signing.key.user.name", and + * "jpackagerTest" can be over-ridden by system property + * "jpackage.mac.signing.keychain" */ /* @@ -72,180 +64,100 @@ */ public class SigningPackageTwoStepTest { - @Test - @ParameterSupplier - public static void test(TestSpec spec) { - MacSign.withKeychain(toConsumer(keychain -> { - spec.test(keychain); - }), SigningBase.StandardKeychain.MAIN.keychain()); - } - - public record TestSpec(Optional signAppImage, Map signPackage) { - - public TestSpec { - Objects.requireNonNull(signAppImage); - Objects.requireNonNull(signPackage); - - if ((signAppImage.isEmpty() && signPackage.isEmpty()) || !PackageType.MAC.containsAll(signPackage.keySet())) { - // Unexpected package types. - throw new IllegalArgumentException(); - } - - // Ensure stable result of toString() call. - if (!SortedMap.class.isInstance(signPackage)) { - signPackage = new TreeMap<>(signPackage); - } + private static void verifyPKG(JPackageCommand cmd) { + if (!cmd.hasArgument("--mac-sign")) { + return; // Nothing to check if not signed } - @Override - public String toString() { - var sb = new StringBuilder(); - - signAppImage.ifPresent(signOption -> { - sb.append(String.format("app-image=%s", signOption)); - }); - - if (!sb.isEmpty() && !signPackage.isEmpty()) { - sb.append("; "); - } - - if (!signPackage.isEmpty()) { - sb.append(signPackage); - } - - return sb.toString(); - } - - boolean signNativeBundle() { - return signPackage.isEmpty(); - } - - static Builder build() { - return new Builder(); - } - - static class Builder { - - TestSpec create() { - return new TestSpec(Optional.ofNullable(signAppImage), signPackage); - } - - Builder certRequest(SigningBase.StandardCertificateRequest v) { - return certRequest(v.spec()); - } - - Builder certRequest(MacSign.CertificateRequest v) { - certRequest = Objects.requireNonNull(v); - return this; - } - - Builder signIdentityType(SignKeyOption.Type v) { - signIdentityType = Objects.requireNonNull(v); - return this; - } - - Builder signAppImage() { - signAppImage = createSignKeyOption(); - return this; - } + Path outputBundle = cmd.outputBundle(); + SigningBase.verifyPkgutil(outputBundle, true, SigningBase.DEFAULT_INDEX); + SigningBase.verifySpctl(outputBundle, "install", SigningBase.DEFAULT_INDEX); + } - Builder signPackage(PackageType type) { - Objects.requireNonNull(type); - signPackage.put(type, createSignKeyOption()); - return this; - } + private static void verifyDMG(JPackageCommand cmd) { + // DMG always unsigned, so we will check it + Path outputBundle = cmd.outputBundle(); + SigningBase.verifyDMG(outputBundle); + } - Builder signPackage() { - PackageType.MAC.forEach(this::signPackage); - return this; + private static void verifyAppImageInDMG(JPackageCommand cmd) { + MacHelper.withExplodedDmg(cmd, dmgImage -> { + // We will be called with all folders in DMG since JDK-8263155, but + // we only need to verify app. + if (dmgImage.endsWith(cmd.name() + ".app")) { + boolean isSigned = cmd.hasArgument("--mac-sign"); + Path launcherPath = ApplicationLayout.platformAppImage() + .resolveAt(dmgImage).launchersDirectory().resolve(cmd.name()); + SigningBase.verifyCodesign(launcherPath, isSigned, SigningBase.DEFAULT_INDEX); + SigningBase.verifyCodesign(dmgImage, isSigned, SigningBase.DEFAULT_INDEX); + if (isSigned) { + SigningBase.verifySpctl(dmgImage, "exec", SigningBase.DEFAULT_INDEX); + } } + }); + } - private SignKeyOption createSignKeyOption() { - return new SignKeyOption(signIdentityType, certRequest); + @Test + // (Signed, "signing-key or sign-identity"}) + // Signed and signing-key + @Parameter({"true", "true"}) + // Signed and signing-identity + @Parameter({"true", "false"}) + // Unsigned + @Parameter({"false", "true"}) + public static void test(boolean signAppImage, boolean signingKey) throws Exception { + Path appimageOutput = TKit.createTempDirectory("appimage"); + + JPackageCommand appImageCmd = JPackageCommand.helloAppImage() + .setArgumentValue("--dest", appimageOutput); + if (signAppImage) { + appImageCmd.addArguments("--mac-sign") + .addArguments("--mac-signing-keychain", + SigningBase.getKeyChain()); + if (signingKey) { + appImageCmd.addArguments("--mac-signing-key-user-name", + SigningBase.getDevName(SigningBase.DEFAULT_INDEX)); + } else { + appImageCmd.addArguments("--mac-app-image-sign-identity", + SigningBase.getAppCert(SigningBase.DEFAULT_INDEX)); } - - private MacSign.CertificateRequest certRequest = SigningBase.StandardCertificateRequest.CODESIGN.spec(); - private SignKeyOption.Type signIdentityType = SignKeyOption.Type.SIGN_KEY_IDENTITY; - - private SignKeyOption signAppImage; - private Map signPackage = new HashMap<>(); } - void test(MacSign.ResolvedKeychain keychain) { - - var appImageCmd = JPackageCommand.helloAppImage().setFakeRuntime(); - MacHelper.useKeychain(appImageCmd, keychain); - signAppImage.ifPresent(signOption -> { - signOption.setTo(appImageCmd); - }); - - var test = new PackageTest(); - - signAppImage.map(SignKeyOption::certRequest).ifPresent(certRequest -> { - // The predefined app image is signed, verify bundled app image is signed too. - test.addInstallVerifier(cmd -> { - MacSignVerify.verifyAppImageSigned(cmd, certRequest, keychain); - }); - }); - - Optional.ofNullable(signPackage.get(PackageType.MAC_PKG)).map(SignKeyOption::certRequest).ifPresent(certRequest -> { - test.forTypes(PackageType.MAC_PKG, () -> { - test.addBundleVerifier(cmd -> { - MacSignVerify.verifyPkgSigned(cmd, certRequest, keychain); - }); - }); - }); - - test.forTypes(signPackage.keySet()).addRunOnceInitializer(() -> { - appImageCmd.setArgumentValue("--dest", TKit.createTempDirectory("appimage")).execute(0); - }).addInitializer(cmd -> { - MacHelper.useKeychain(cmd, keychain); - cmd.addArguments("--app-image", appImageCmd.outputBundle()); - cmd.removeArgumentWithValue("--input"); - Optional.ofNullable(signPackage.get(cmd.packageType())).ifPresent(signOption -> { - signOption.setTo(cmd); - }); - - if (signAppImage.isPresent()) { - // Predefined app image is signed. Expect a warning. - cmd.validateOutput(JPackageStringBundle.MAIN.cannedFormattedString( - "warning.per.user.app.image.signed", - PackageFile.getPathInAppImage(Path.of("")))); - } else if (cmd.packageType() == PackageType.MAC_PKG && signPackage.containsKey(cmd.packageType())) { - // Create signed ".pkg" bundle from the unsigned predefined app image. Expect a warning. - cmd.validateOutput(JPackageStringBundle.MAIN.cannedFormattedString("warning.unsigned.app.image", "pkg")); - } - }) - .run(); - } - } - - public static Collection test() { - - List data = new ArrayList<>(); - - Stream.of(SignKeyOption.Type.values()).flatMap(signIdentityType -> { - return Stream.of( - // Sign both predefined app image and native package. - TestSpec.build().signIdentityType(signIdentityType) - .signAppImage() - .signPackage() - .certRequest(SigningBase.StandardCertificateRequest.PKG) - .signPackage(PackageType.MAC_PKG), - - // Don't sign predefined app image, sign native package. - TestSpec.build().signIdentityType(signIdentityType) - .signPackage() - .certRequest(SigningBase.StandardCertificateRequest.PKG) - .signPackage(PackageType.MAC_PKG), - - // Sign predefined app image, don't sign native package. - TestSpec.build().signIdentityType(signIdentityType).signAppImage() - ); - }).forEach(data::add); - - return data.stream().map(TestSpec.Builder::create).map(v -> { - return new Object[] {v}; - }).toList(); + new PackageTest() + .addRunOnceInitializer(() -> appImageCmd.execute()) + .forTypes(PackageType.MAC) + .addInitializer(cmd -> { + cmd.addArguments("--app-image", appImageCmd.outputBundle()); + cmd.removeArgumentWithValue("--input"); + if (signAppImage) { + cmd.addArguments("--mac-sign", + "--mac-signing-keychain", + SigningBase.getKeyChain()); + if (signingKey) { + cmd.addArguments("--mac-signing-key-user-name", + SigningBase.getDevName(SigningBase.DEFAULT_INDEX)); + } else { + cmd.addArguments("--mac-installer-sign-identity", + SigningBase.getInstallerCert(SigningBase.DEFAULT_INDEX)); + } + } + }) + .forTypes(PackageType.MAC_PKG) + .addBundleVerifier(SigningPackageTwoStepTest::verifyPKG) + .forTypes(PackageType.MAC_DMG) + .addInitializer(cmd -> { + if (signAppImage && !signingKey) { + // jpackage throws expected error with + // --mac-installer-sign-identity and DMG type + cmd.removeArgumentWithValue("--mac-installer-sign-identity"); + // It will do nothing, but it signals test that app + // image itself is signed for verification. + cmd.addArguments("--mac-app-image-sign-identity", + SigningBase.getAppCert(SigningBase.DEFAULT_INDEX)); + } + }) + .addBundleVerifier(SigningPackageTwoStepTest::verifyDMG) + .addBundleVerifier(SigningPackageTwoStepTest::verifyAppImageInDMG) + .run(); } } diff --git a/test/jdk/tools/jpackage/macosx/SigningRuntimeImagePackageTest.java b/test/jdk/tools/jpackage/macosx/SigningRuntimeImagePackageTest.java index efcaadc3fa82f..b137824a910f5 100644 --- a/test/jdk/tools/jpackage/macosx/SigningRuntimeImagePackageTest.java +++ b/test/jdk/tools/jpackage/macosx/SigningRuntimeImagePackageTest.java @@ -21,53 +21,51 @@ * questions. */ -import static jdk.jpackage.internal.util.function.ThrowingConsumer.toConsumer; - import java.io.IOException; import java.nio.file.Path; import java.util.function.Predicate; import java.util.stream.Stream; + import jdk.jpackage.test.Annotations.Parameter; import jdk.jpackage.test.Annotations.Test; import jdk.jpackage.test.Executor; import jdk.jpackage.test.JPackageCommand; import jdk.jpackage.test.MacHelper; -import jdk.jpackage.test.MacSign; import jdk.jpackage.test.PackageTest; import jdk.jpackage.test.PackageType; import jdk.jpackage.test.TKit; /** - * Tests generation of dmg and pkg with --mac-sign and related arguments. Test - * will generate pkg and verifies its signature. It verifies that dmg is not - * signed, but runtime image inside dmg is signed. + * Tests generation of dmg and pkg with --mac-sign and related arguments. + * Test will generate pkg and verifies its signature. It verifies that dmg + * is not signed, but runtime image inside dmg is signed. * - *

    - * Note: Specific UNICODE signing is not tested, since it is shared code with - * app image signing and it will be covered by SigningPackageTest. + * Note: Specific UNICODE signing is not tested, since it is shared code + * with app image signing and it will be covered by SigningPackageTest. * - *

    * Following combinations are tested: - *

      - *
    1. "--runtime-image" points to unsigned JDK bundle and --mac-sign is not + * 1) "--runtime-image" points to unsigned JDK bundle and --mac-sign is not * provided. Expected result: runtime image ad-hoc signed. - *
    2. "--runtime-image" points to unsigned JDK bundle and --mac-sign is + * 2) "--runtime-image" points to unsigned JDK bundle and --mac-sign is * provided. Expected result: Everything is signed with provided certificate. - *
    3. "--runtime-image" points to signed JDK bundle and --mac-sign is not + * 3) "--runtime-image" points to signed JDK bundle and --mac-sign is not * provided. Expected result: runtime image is signed with original certificate. - *
    4. "--runtime-image" points to signed JDK bundle and --mac-sign is provided. + * 4) "--runtime-image" points to signed JDK bundle and --mac-sign is provided. * Expected result: runtime image is signed with provided certificate. - *
    5. "--runtime-image" points to JDK image and --mac-sign is not provided. + * 5) "--runtime-image" points to JDK image and --mac-sign is not provided. * Expected result: runtime image ad-hoc signed. - *
    6. "--runtime-image" points to JDK image and --mac-sign is provided. + * 6) "--runtime-image" points to JDK image and --mac-sign is provided. * Expected result: Everything is signed with provided certificate. - *
    * * This test requires that the machine is configured with test certificate for - * "Developer ID Installer: jpackage.openjdk.java.net" in jpackagerTest keychain - * with always allowed access to this keychain for user which runs test. note: + * "Developer ID Installer: jpackage.openjdk.java.net" in + * jpackagerTest keychain with + * always allowed access to this keychain for user which runs test. + * note: * "jpackage.openjdk.java.net" can be over-ridden by system property - * "jpackage.mac.signing.key.user.name" + * "jpackage.mac.signing.key.user.name", and + * "jpackagerTest" can be over-ridden by system property + * "jpackage.mac.signing.keychain" */ /* @@ -86,17 +84,17 @@ */ public class SigningRuntimeImagePackageTest { - private static JPackageCommand addSignOptions(JPackageCommand cmd, MacSign.ResolvedKeychain keychain, int certIndex) { + private static JPackageCommand addSignOptions(JPackageCommand cmd, int certIndex) { if (certIndex != SigningBase.CertIndex.INVALID_INDEX.value()) { cmd.addArguments( "--mac-sign", - "--mac-signing-keychain", keychain.name(), + "--mac-signing-keychain", SigningBase.getKeyChain(), "--mac-signing-key-user-name", SigningBase.getDevName(certIndex)); } return cmd; } - private static Path createInputRuntimeBundle(MacSign.ResolvedKeychain keychain, int certIndex) throws IOException { + private static Path createInputRuntimeBundle(int certIndex) throws IOException { final var runtimeImage = JPackageCommand.createInputRuntimeImage(); @@ -113,7 +111,7 @@ private static Path createInputRuntimeBundle(MacSign.ResolvedKeychain keychain, .addArguments("--runtime-image", runtimeImage) .addArguments("--dest", runtimeBundleWorkDir); - addSignOptions(cmd, keychain, certIndex); + addSignOptions(cmd, certIndex); cmd.execute(); @@ -149,21 +147,13 @@ private static Path createInputRuntimeBundle(MacSign.ResolvedKeychain keychain, public static void test(boolean useJDKBundle, SigningBase.CertIndex jdkBundleCert, SigningBase.CertIndex signCert) throws Exception { - MacSign.withKeychain(toConsumer(keychain -> { - test(keychain, useJDKBundle, jdkBundleCert, signCert); - }), SigningBase.StandardKeychain.MAIN.keychain()); - } - - private static void test(MacSign.ResolvedKeychain keychain, boolean useJDKBundle, - SigningBase.CertIndex jdkBundleCert, - SigningBase.CertIndex signCert) throws Exception { final Path inputRuntime[] = new Path[1]; new PackageTest() .addRunOnceInitializer(() -> { if (useJDKBundle) { - inputRuntime[0] = createInputRuntimeBundle(keychain, jdkBundleCert.value()); + inputRuntime[0] = createInputRuntimeBundle(jdkBundleCert.value()); } else { inputRuntime[0] = JPackageCommand.createInputRuntimeImage(); } @@ -174,7 +164,7 @@ private static void test(MacSign.ResolvedKeychain keychain, boolean useJDKBundle // create input directory in the test and jpackage fails // if --input references non existent directory. cmd.removeArgumentWithValue("--input"); - addSignOptions(cmd, keychain, signCert.value()); + addSignOptions(cmd, signCert.value()); }) .addInstallVerifier(cmd -> { final var certIndex = Stream.of(signCert, jdkBundleCert) diff --git a/test/jdk/tools/jpackage/macosx/base/SigningBase.java b/test/jdk/tools/jpackage/macosx/base/SigningBase.java index 1e38f9b0c29a9..5484245f111dd 100644 --- a/test/jdk/tools/jpackage/macosx/base/SigningBase.java +++ b/test/jdk/tools/jpackage/macosx/base/SigningBase.java @@ -90,29 +90,17 @@ private static CertificateRequest.Builder cert() { private final CertificateRequest spec; } - /** - * Standard keychains used in signing tests. - */ public enum StandardKeychain { - /** - * The primary keychain with good certificates. - */ - MAIN("jpackagerTest.keychain", + MAIN(DEFAULT_KEYCHAIN, StandardCertificateRequest.CODESIGN, StandardCertificateRequest.PKG, StandardCertificateRequest.CODESIGN_UNICODE, StandardCertificateRequest.PKG_UNICODE), - /** - * A keychain with some good and some expired certificates. - */ EXPIRED("jpackagerTest-expired.keychain", StandardCertificateRequest.CODESIGN, StandardCertificateRequest.PKG, StandardCertificateRequest.CODESIGN_EXPIRED, StandardCertificateRequest.PKG_EXPIRED), - /** - * A keychain with duplicated certificates. - */ DUPLICATE("jpackagerTest-duplicate.keychain", StandardCertificateRequest.CODESIGN, StandardCertificateRequest.PKG, @@ -126,26 +114,30 @@ public enum StandardKeychain { StandardKeychain(String keychainName, CertificateRequest cert, CertificateRequest... otherCerts) { final var builder = keychain(keychainName).addCert(cert); List.of(otherCerts).forEach(builder::addCert); - this.keychain = new ResolvedKeychain(builder.create()); + this.spec = new ResolvedKeychain(builder.create()); } - public ResolvedKeychain keychain() { - return keychain; + public KeychainWithCertsSpec spec() { + return spec.spec(); } public X509Certificate mapCertificateRequest(CertificateRequest certRequest) { - return Objects.requireNonNull(keychain.mapCertificateRequests().get(certRequest)); + return Objects.requireNonNull(spec.mapCertificateRequests().get(certRequest)); } private static KeychainWithCertsSpec.Builder keychain(String name) { return new KeychainWithCertsSpec.Builder().name(name); } + private static CertificateRequest.Builder cert() { + return new CertificateRequest.Builder(); + } + private static List signingEnv() { - return Stream.of(values()).map(StandardKeychain::keychain).map(ResolvedKeychain::spec).toList(); + return Stream.of(values()).map(StandardKeychain::spec).toList(); } - private final ResolvedKeychain keychain; + private final ResolvedKeychain spec; } public static void setUp() { @@ -187,6 +179,7 @@ int value() { "jpackage.openjdk.java.net", "jpackage.openjdk.java.net (ö)", }; + private static String DEFAULT_KEYCHAIN = "jpackagerTest.keychain"; public static String getDevName(int certIndex) { // Always use values from system properties if set @@ -202,6 +195,16 @@ public static int getDevNameIndex(String devName) { return Arrays.binarySearch(DEV_NAMES, devName); } + // Returns 'true' if dev name from DEV_NAMES + public static boolean isDevNameDefault() { + String value = System.getProperty("jpackage.mac.signing.key.user.name"); + if (value != null) { + return false; + } + + return true; + } + public static String getAppCert(int certIndex) { return "Developer ID Application: " + getDevName(certIndex); } @@ -210,6 +213,16 @@ public static String getInstallerCert(int certIndex) { return "Developer ID Installer: " + getDevName(certIndex); } + public static String getKeyChain() { + // Always use values from system properties if set + String value = System.getProperty("jpackage.mac.signing.keychain"); + if (value != null) { + return value; + } + + return DEFAULT_KEYCHAIN; + } + public static void verifyCodesign(Path target, boolean signed, int certIndex) { if (signed) { final var certRequest = getCertRequest(certIndex); diff --git a/test/jdk/tools/jpackage/share/AddLShortcutTest.java b/test/jdk/tools/jpackage/share/AddLShortcutTest.java index f000e79227e76..9c50c6ffc98ca 100644 --- a/test/jdk/tools/jpackage/share/AddLShortcutTest.java +++ b/test/jdk/tools/jpackage/share/AddLShortcutTest.java @@ -118,12 +118,6 @@ public void test() { HelloApp.createBundle(JavaAppDesc.parse(addLauncherApp + "*another.jar:Welcome"), cmd.inputDir()); }); - if (RunnablePackageTest.hasAction(RunnablePackageTest.Action.INSTALL)) { - // Ensure launchers are executable because the output bundle will be installed - // and launchers will be attempted to be executed through their shortcuts. - packageTest.addInitializer(JPackageCommand::ignoreFakeRuntime); - } - new FileAssociations(packageName).applyTo(packageTest); new AdditionalLauncher("Foo") diff --git a/test/jdk/tools/jpackage/share/AddLauncherTest.java b/test/jdk/tools/jpackage/share/AddLauncherTest.java index 21f475cbd7810..a7bfbf376edb8 100644 --- a/test/jdk/tools/jpackage/share/AddLauncherTest.java +++ b/test/jdk/tools/jpackage/share/AddLauncherTest.java @@ -21,22 +21,18 @@ * questions. */ -import java.lang.invoke.MethodHandles; import java.nio.file.Path; -import java.util.function.Consumer; -import jdk.internal.util.OperatingSystem; -import jdk.jpackage.test.AdditionalLauncher; -import jdk.jpackage.test.Annotations.Parameter; -import jdk.jpackage.test.Annotations.Test; -import jdk.jpackage.test.CfgFile; -import jdk.jpackage.test.ConfigurationTarget; +import java.util.Map; +import java.lang.invoke.MethodHandles; +import jdk.jpackage.test.PackageTest; import jdk.jpackage.test.FileAssociations; +import jdk.jpackage.test.AdditionalLauncher; import jdk.jpackage.test.JPackageCommand; import jdk.jpackage.test.JavaAppDesc; -import jdk.jpackage.test.PackageTest; -import jdk.jpackage.test.PackageType; -import jdk.jpackage.test.RunnablePackageTest.Action; import jdk.jpackage.test.TKit; +import jdk.jpackage.test.Annotations.Test; +import jdk.jpackage.test.Annotations.Parameter; +import jdk.jpackage.test.CfgFile; /** * Test --add-launcher parameter. Output of the test should be @@ -237,61 +233,6 @@ public void testMainLauncherIsModular(boolean mainLauncherIsModular) { "Check app.classpath value in ModularAppLauncher cfg file"); } - /** - * Test --description option - */ - @Test(ifNotOS = OperatingSystem.MACOS) // Don't run on macOS as launcher description is ignored on this platform - @Parameter("true") - @Parameter("fase") - public void testDescription(boolean withPredefinedAppImage) { - - ConfigurationTarget target; - if (TKit.isWindows() || withPredefinedAppImage) { - target = new ConfigurationTarget(JPackageCommand.helloAppImage()); - } else { - target = new ConfigurationTarget(new PackageTest().configureHelloApp()); - } - - target.addInitializer(cmd -> { - cmd.setArgumentValue("--name", "Foo").setArgumentValue("--description", "Hello"); - cmd.setFakeRuntime(); - cmd.setStandardAsserts(JPackageCommand.StandardAssert.MAIN_LAUNCHER_DESCRIPTION); - }); - - target.add(new AdditionalLauncher("x")); - target.add(new AdditionalLauncher("bye").setProperty("description", "Bye")); - - target.test().ifPresent(test -> { - // Make all launchers have shortcuts and thus .desktop files. - // Launcher description is recorded in a desktop file and verified automatically. - test.mutate(addLinuxShortcuts()); - }); - - target.cmd().ifPresent(withPredefinedAppImage ? JPackageCommand::execute : JPackageCommand::executeAndAssertImageCreated); - target.test().ifPresent(test -> { - test.run(Action.CREATE_AND_UNPACK); - }); - - if (withPredefinedAppImage) { - new PackageTest().addInitializer(cmd -> { - cmd.setArgumentValue("--name", "Bar"); - // Should not have impact of launcher descriptions, but it does. - cmd.setArgumentValue("--description", "Installer"); - cmd.removeArgumentWithValue("--input").setArgumentValue("--app-image", target.cmd().orElseThrow().outputBundle()); - }).mutate(addLinuxShortcuts()).run(Action.CREATE_AND_UNPACK); - } - } - - private static Consumer addLinuxShortcuts() { - return test -> { - test.forTypes(PackageType.LINUX, () -> { - test.addInitializer(cmd -> { - cmd.addArgument("--linux-shortcut"); - }); - }); - }; - } - private static final Path GOLDEN_ICON = TKit.TEST_SRC_ROOT.resolve(Path.of( "resources", "icon" + TKit.ICON_SUFFIX)); } diff --git a/test/jdk/tools/jpackage/share/AppContentTest.java b/test/jdk/tools/jpackage/share/AppContentTest.java index 5b5734df61d1a..2c6498a631b83 100644 --- a/test/jdk/tools/jpackage/share/AppContentTest.java +++ b/test/jdk/tools/jpackage/share/AppContentTest.java @@ -21,43 +21,24 @@ * questions. */ -import static java.util.Map.entry; -import static java.util.stream.Collectors.joining; -import static java.util.stream.Collectors.toMap; +import static jdk.internal.util.OperatingSystem.LINUX; import static jdk.internal.util.OperatingSystem.MACOS; -import static jdk.internal.util.OperatingSystem.WINDOWS; -import static jdk.jpackage.internal.util.function.ThrowingFunction.toFunction; +import static java.util.stream.Collectors.joining; import java.io.IOException; -import java.io.UncheckedIOException; import java.nio.file.Files; -import java.nio.file.NoSuchFileException; import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashSet; +import jdk.jpackage.test.PackageTest; +import jdk.jpackage.test.TKit; +import jdk.jpackage.test.Annotations.Test; +import jdk.jpackage.test.Annotations.Parameter; +import java.util.Arrays; import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Optional; -import java.util.Set; -import java.util.TreeMap; -import java.util.function.Predicate; -import java.util.function.Supplier; import java.util.stream.Stream; -import java.util.stream.StreamSupport; import jdk.jpackage.internal.util.FileUtils; -import jdk.jpackage.internal.util.IdentityWrapper; -import jdk.jpackage.internal.util.function.ThrowingSupplier; -import jdk.jpackage.test.Annotations.Parameter; -import jdk.jpackage.test.Annotations.ParameterSupplier; -import jdk.jpackage.test.Annotations.Test; -import jdk.jpackage.test.ConfigurationTarget; +import jdk.jpackage.internal.util.function.ThrowingFunction; import jdk.jpackage.test.JPackageCommand; import jdk.jpackage.test.JPackageStringBundle; -import jdk.jpackage.test.PackageTest; -import jdk.jpackage.test.PackageType; -import jdk.jpackage.test.TKit; /** @@ -76,23 +57,68 @@ */ public class AppContentTest { - @Test - @ParameterSupplier - @ParameterSupplier(value="testSymlink", ifNotOS = WINDOWS) - public void test(TestSpec testSpec) throws Exception { - testSpec.test(new ConfigurationTarget(new PackageTest().configureHelloApp())); - } + private static final String TEST_JAVA = "apps/PrintEnv.java"; + private static final String TEST_DUKE = "apps/dukeplug.png"; + private static final String TEST_DUKE_LINK = "dukeplugLink.txt"; + private static final String TEST_DIR = "apps"; + private static final String TEST_BAD = "non-existant"; + + // On OSX `--app-content` paths will be copied into the "Contents" folder + // of the output app image. + // "codesign" imposes restrictions on the directory structure of "Contents" folder. + // In particular, random files should be placed in "Contents/Resources" folder + // otherwise "codesign" will fail to sign. + // Need to prepare arguments for `--app-content` accordingly. + private static final boolean copyInResources = TKit.isOSX(); + + private static final String RESOURCES_DIR = "Resources"; + private static final String LINKS_DIR = "Links"; @Test - @ParameterSupplier("test") - @ParameterSupplier(value="testSymlink", ifNotOS = WINDOWS) - public void testAppImage(TestSpec testSpec) throws Exception { - testSpec.test(new ConfigurationTarget(JPackageCommand.helloAppImage())); + // include two files in two options + @Parameter({TEST_JAVA, TEST_DUKE}) + // try to include non-existant content + @Parameter({TEST_JAVA, TEST_BAD}) + // two files in one option and a dir tree in another option. + @Parameter({TEST_JAVA + "," + TEST_DUKE, TEST_DIR}) + // include one file and one link to the file + @Parameter(value = {TEST_JAVA, TEST_DUKE_LINK}, ifOS = {MACOS,LINUX}) + public void test(String... args) throws Exception { + final List testPathArgs = List.of(args); + final int expectedJPackageExitCode; + if (testPathArgs.contains(TEST_BAD)) { + expectedJPackageExitCode = 1; + } else { + expectedJPackageExitCode = 0; + } + + var appContentInitializer = new AppContentInitializer(testPathArgs); + + new PackageTest().configureHelloApp() + .addRunOnceInitializer(appContentInitializer::initAppContent) + .addInitializer(appContentInitializer::applyTo) + .addInstallVerifier(cmd -> { + for (String arg : testPathArgs) { + List paths = Arrays.asList(arg.split(",")); + for (String p : paths) { + Path name = Path.of(p).getFileName(); + if (isSymlinkPath(name)) { + TKit.assertSymbolicLinkExists(getAppContentRoot(cmd) + .resolve(LINKS_DIR).resolve(name)); + } else { + TKit.assertPathExists(getAppContentRoot(cmd) + .resolve(name), true); + } + } + } + }) + .setExpectedExitCode(expectedJPackageExitCode) + .run(); } @Test(ifOS = MACOS) - @Parameter({"apps", "warning.non.standard.contents.sub.dir"}) - @Parameter({"apps/dukeplug.png", "warning.app.content.is.not.dir"}) + @Parameter({TEST_DIR, "warning.non.standard.contents.sub.dir"}) + @Parameter({TEST_DUKE, "warning.app.content.is.not.dir"}) public void testWarnings(String testPath, String warningId) throws Exception { final var appContentValue = TKit.TEST_SRC_ROOT.resolve(testPath); final var expectedWarning = JPackageStringBundle.MAIN.cannedFormattedString( @@ -100,588 +126,96 @@ public void testWarnings(String testPath, String warningId) throws Exception { JPackageCommand.helloAppImage() .addArguments("--app-content", appContentValue) - .setFakeRuntime() .validateOutput(expectedWarning) .executeIgnoreExitCode(); } - public static Collection test() { - return Stream.of( - build().add(TEST_JAVA).add(TEST_DUKE), - build().add(TEST_JAVA).add(TEST_BAD), - build().startGroup().add(TEST_JAVA).add(TEST_DUKE).endGroup().add(TEST_DIR), - // Same directory specified multiple times. - build().add(TEST_DIR).add(TEST_DIR), - // Same file specified multiple times. - build().add(TEST_JAVA).add(TEST_JAVA), - // Two files with the same name but different content. - build() - .add(createTextFileContent("welcome.txt", "Welcome")) - .add(createTextFileContent("welcome.txt", "Benvenuti")), - // Same name: one is a directory, another is a file. - build().add(createTextFileContent("a/b/c/d", "Foo")).add(createTextFileContent("a", "Bar")), - // Same name: one is a file, another is a directory. - build().add(createTextFileContent("a", "Bar")).add(createTextFileContent("a/b/c/d", "Foo")) - ).map(TestSpec.Builder::create).map(v -> { - return new Object[] {v}; - }).toList(); - } - - public static Collection testSymlink() { - return Stream.of( - build().add(TEST_JAVA) - .add(new SymlinkContentFactory("Links", "duke-link", "duke-target")) - .add(new SymlinkContentFactory("", "a/b/foo-link", "c/bar-target")) - ).map(TestSpec.Builder::create).map(v -> { - return new Object[] {v}; - }).toList(); - } - - public record TestSpec(List> contentFactories) { - public TestSpec { - contentFactories.stream().flatMap(List::stream).forEach(Objects::requireNonNull); - } - - @Override - public String toString() { - return contentFactories.stream().map(group -> { - return group.stream().map(ContentFactory::toString).collect(joining(",")); - }).collect(joining("; ")); - } - - void test(ConfigurationTarget target) { - final int expectedJPackageExitCode; - if (contentFactories.stream().flatMap(List::stream).anyMatch(TEST_BAD::equals)) { - expectedJPackageExitCode = 1; - } else { - expectedJPackageExitCode = 0; - } - - final List> allContent = new ArrayList<>(); - - target.addInitializer(JPackageCommand::setFakeRuntime) - .addRunOnceInitializer(_ -> { - contentFactories.stream().map(group -> { - return group.stream().map(ContentFactory::create).toList(); - }).forEach(allContent::add); - }).addInitializer(cmd -> { - allContent.stream().map(group -> { - return Stream.of("--app-content", group.stream() - .map(Content::paths) - .flatMap(List::stream) - .map(appContentArg -> { - if (COPY_IN_RESOURCES && Optional.ofNullable(appContentArg.getParent()) - .map(Path::getFileName) - .map(RESOURCES_DIR::equals) - .orElse(false)) { - return appContentArg.getParent(); - } else { - return appContentArg; - } - }) - .map(Path::toString) - .collect(joining(","))); - }).flatMap(x -> x).forEachOrdered(cmd::addArgument); - }); - - target.cmd().ifPresent(cmd -> { - if (expectedJPackageExitCode == 0) { - cmd.executeAndAssertImageCreated(); - } else { - cmd.execute(expectedJPackageExitCode); - } - }); - - target.addInstallVerifier(cmd -> { - var appContentRoot = getAppContentRoot(cmd); - - Set disabledVerifiers = new HashSet<>(); - - var verifiers = allContent.stream().flatMap(List::stream).flatMap(content -> { - return StreamSupport.stream(content.verifiers(appContentRoot).spliterator(), false).map(verifier -> { - return new PathVerifierWithOrigin(verifier, content); - }); - }).collect(toMap(PathVerifierWithOrigin::path, x -> x, (first, second) -> { - // The same file in the content directory is sourced from multiple origins. - // jpackage will handle this case such that the following origins overwrite preceding origins. - // Scratch all path verifiers affected by overrides. - first.getNestedVerifiers(appContentRoot, first.path()).forEach(disabledVerifiers::add); - return second; - }, TreeMap::new)).values().stream() - .map(PathVerifierWithOrigin::verifier) - .filter(Predicate.not(disabledVerifiers::contains)) - .filter(verifier -> { - if (!(verifier instanceof DirectoryVerifier dirVerifier)) { - return true; - } else { - try { - // Run the directory verifier if the directory is empty. - // Otherwise, it just pollutes the test log. - return isDirectoryEmpty(verifier.path()); - } catch (NoSuchFileException ex) { - // If an MSI contains an empty directory, it will be installed but not created when the MSI is unpacked. - // In the latter the control flow will reach this point. - if (dirVerifier.isEmpty() - && PackageType.WINDOWS.contains(cmd.packageType()) - && cmd.isPackageUnpacked(String.format( - "Expected empty directory [%s] is missing", verifier.path()))) { - return false; - } - throw new UncheckedIOException(ex); - } catch (IOException ex) { - throw new UncheckedIOException(ex); - } - } - }) - .toList(); - - verifiers.forEach(PathVerifier::verify); - }); - - target.test().ifPresent(test -> { - test.setExpectedExitCode(expectedJPackageExitCode).run(); - }); - } - - static final class Builder { - TestSpec create() { - return new TestSpec(groups); - } - - final class GroupBuilder { - GroupBuilder add(ContentFactory cf) { - group.add(Objects.requireNonNull(cf)); - return this; - } - - Builder endGroup() { - if (!group.isEmpty()) { - groups.add(group); - } - return Builder.this; - } - - private final List group = new ArrayList<>(); - } - - Builder add(ContentFactory cf) { - return startGroup().add(cf).endGroup(); - } - - GroupBuilder startGroup() { - return new GroupBuilder(); - } - - private final List> groups = new ArrayList<>(); - } - - private record PathVerifierWithOrigin(PathVerifier verifier, Content origin) { - PathVerifierWithOrigin { - Objects.requireNonNull(verifier); - Objects.requireNonNull(origin); - } - - Path path() { - return verifier.path(); - } - - Stream getNestedVerifiers(Path appContentRoot, Path path) { - if (!path.startsWith(appContentRoot)) { - throw new IllegalArgumentException(); - } - - return StreamSupport.stream(origin.verifiers(appContentRoot).spliterator(), false).filter(v -> { - return v.path().getNameCount() > path.getNameCount() && v.path().startsWith(path); - }); - } - } - } - - private static TestSpec.Builder build() { - return new TestSpec.Builder(); - } - private static Path getAppContentRoot(JPackageCommand cmd) { - final Path contentDir = cmd.appLayout().contentDirectory(); - if (COPY_IN_RESOURCES) { + Path contentDir = cmd.appLayout().contentDirectory(); + if (copyInResources) { return contentDir.resolve(RESOURCES_DIR); } else { return contentDir; } } - private static Path createAppContentRoot() { - if (COPY_IN_RESOURCES) { - return TKit.createTempDirectory("app-content").resolve(RESOURCES_DIR); - } else { - return TKit.createTempDirectory("app-content"); - } - } - - private static boolean isDirectoryEmpty(Path path) throws IOException { - if (Files.exists(path) && !Files.isDirectory(path)) { - throw new IllegalArgumentException(); - } - - try (var files = Files.list(path)) { - return files.findAny().isEmpty(); - } - } - - @FunctionalInterface - private interface ContentFactory { - Content create(); - } - - private interface Content { - List paths(); - Iterable verifiers(Path appContentRoot); - } - - private sealed interface PathVerifier permits - RegularFileVerifier, - DirectoryVerifier, - SymlinkTargetVerifier, - NoPathVerifier { - - Path path(); - void verify(); - } - - private record RegularFileVerifier(Path path, Path srcFile) implements PathVerifier { - RegularFileVerifier { - Objects.requireNonNull(path); - Objects.requireNonNull(srcFile); - } - - @Override - public void verify() { - TKit.assertSameFileContent(srcFile, path); - } + private static boolean isSymlinkPath(Path v) { + return v.getFileName().toString().contains("Link"); } - private record DirectoryVerifier(Path path, boolean isEmpty, IdentityWrapper origin) implements PathVerifier { - DirectoryVerifier { - Objects.requireNonNull(path); + private static final class AppContentInitializer { + AppContentInitializer(List appContentArgs) { + appContentPathGroups = appContentArgs.stream().map(arg -> { + return Stream.of(arg.split(",")).map(Path::of).toList(); + }).toList(); } - @Override - public void verify() { - if (isEmpty) { - TKit.assertDirectoryEmpty(path); - } else { - TKit.assertDirectoryExists(path); - } + void initAppContent() { + jpackageArgs = appContentPathGroups.stream() + .map(AppContentInitializer::initAppContentPaths) + .mapMulti((appContentPaths, consumer) -> { + consumer.accept("--app-content"); + consumer.accept( + appContentPaths.stream().map(Path::toString).collect( + joining(","))); + }).toList(); } - } - private record SymlinkTargetVerifier(Path path, Path targetPath) implements PathVerifier { - SymlinkTargetVerifier { - Objects.requireNonNull(path); - Objects.requireNonNull(targetPath); + void applyTo(JPackageCommand cmd) { + cmd.addArguments(jpackageArgs); } - @Override - public void verify() { - TKit.assertSymbolicLinkTarget(path, targetPath); + private static Path copyAppContentPath(Path appContentPath) throws IOException { + var appContentArg = TKit.createTempDirectory("app-content").resolve(RESOURCES_DIR); + var srcPath = TKit.TEST_SRC_ROOT.resolve(appContentPath); + var dstPath = appContentArg.resolve(srcPath.getFileName()); + FileUtils.copyRecursive(srcPath, dstPath); + return appContentArg; } - } - - private record NoPathVerifier(Path path) implements PathVerifier { - NoPathVerifier { - Objects.requireNonNull(path); - } - - @Override - public void verify() { - TKit.assertPathExists(path, false); - } - } - - private record FileContent(Path path, int level) implements Content { - - FileContent { - Objects.requireNonNull(path); - if ((level < 0) || (path.getNameCount() <= level)) { - throw new IllegalArgumentException(); - } - } - - @Override - public List paths() { - return List.of(appContentOptionValue()); - } - - @Override - public Iterable verifiers(Path appContentRoot) { - List verifiers = new ArrayList<>(); - - var appContentPath = appContentRoot.resolve(pathInAppContentRoot()); - - if (Files.isDirectory(path)) { - try (var walk = Files.walk(path)) { - verifiers.addAll(walk.map(srcFile -> { - var dstFile = appContentPath.resolve(path.relativize(srcFile)); - if (Files.isRegularFile(srcFile)) { - return new RegularFileVerifier(dstFile, srcFile); - } else { - return new DirectoryVerifier(dstFile, - toFunction(AppContentTest::isDirectoryEmpty).apply(srcFile), - new IdentityWrapper<>(this)); - } - }).toList()); - } catch (IOException ex) { - throw new UncheckedIOException(ex); - } - } else if (Files.isRegularFile(path)) { - verifiers.add(new RegularFileVerifier(appContentPath, path)); - } else { - verifiers.add(new NoPathVerifier(appContentPath)); - } - - if (level > 0) { - var cur = appContentPath; - for (int i = 0; i != level; i++) { - cur = cur.getParent(); - verifiers.add(new DirectoryVerifier(cur, false, new IdentityWrapper<>(this))); - } - } - - return verifiers; - } - - private Path appContentOptionValue() { - var cur = path; - for (int i = 0; i != level; i++) { - cur = cur.getParent(); - } - return cur; - } - - private Path pathInAppContentRoot() { - return StreamSupport.stream(path.spliterator(), false) - .skip(path.getNameCount() - level - 1) - .reduce(Path::resolve).orElseThrow(); - } - } - - /** - * Non-existing content. - */ - private static final class NonExistantPath implements ContentFactory { - @Override - public Content create() { - var nonExistant = TKit.createTempFile("non-existant"); - try { - TKit.deleteIfExists(nonExistant); - } catch (IOException ex) { - throw new UncheckedIOException(ex); - } - return new FileContent(nonExistant, 0); - } - - @Override - public String toString() { - return "*non-existant*"; - } - } - - /** - * Creates a content from a directory tree. - * - * @param path name of directory where to create a directory tree - */ - private static ContentFactory createDirTreeContent(Path path) { - if (path.isAbsolute()) { - throw new IllegalArgumentException(); - } - - return new FileContentFactory(() -> { - var basedir = TKit.createTempDirectory("content").resolve(path); - - for (var textFile : Map.ofEntries( - entry("woods/moose", "The moose"), - entry("woods/bear", "The bear"), - entry("woods/trees/jay", "The gray jay") - ).entrySet()) { - var src = basedir.resolve(textFile.getKey()); - Files.createDirectories(src.getParent()); - TKit.createTextFile(src, Stream.of(textFile.getValue())); - } - - for (var emptyDir : List.of("sky")) { - Files.createDirectories(basedir.resolve(emptyDir)); - } - - return basedir; - }, path); - } - - private static ContentFactory createDirTreeContent(String path) { - return createDirTreeContent(Path.of(path)); - } - - /** - * Creates a content from a text file. - * - * @param path the path where to copy the text file in app image's content directory - * @param lines the content of the source text file - */ - private static ContentFactory createTextFileContent(Path path, String ... lines) { - if (path.isAbsolute()) { - throw new IllegalArgumentException(); - } - - return new FileContentFactory(() -> { - var srcPath = TKit.createTempDirectory("content").resolve(path); - Files.createDirectories(srcPath.getParent()); - TKit.createTextFile(srcPath, Stream.of(lines)); - return srcPath; - }, path); - } - - private static ContentFactory createTextFileContent(String path, String ... lines) { - return createTextFileContent(Path.of(path), lines); - } - - /** - * Symlink content factory. - * - * @path basedir the directory where to write the content in app image's content - * directory - * @param symlink the path to the symlink relative to {@code basedir} path - * @param symlinked the path to the source file for the symlink - */ - private record SymlinkContentFactory(Path basedir, Path symlink, Path symlinked) implements ContentFactory { - SymlinkContentFactory { - for (final var path : List.of(basedir, symlink, symlinked)) { - if (path.isAbsolute()) { - throw new IllegalArgumentException(); - } - } - } - - SymlinkContentFactory(String basedir, String symlink, String symlinked) { - this(Path.of(basedir), Path.of(symlink), Path.of(symlinked)); - } - - @Override - public Content create() { - final var appContentRoot = createAppContentRoot(); - - final var symlinkPath = appContentRoot.resolve(symlinkPath()); - final var symlinkedPath = appContentRoot.resolve(symlinkedPath()); - try { - Files.createDirectories(symlinkPath.getParent()); - Files.createDirectories(symlinkedPath.getParent()); - // Create the target file for the link. - Files.writeString(symlinkedPath, symlinkedPath().toString()); - // Create the link. - Files.createSymbolicLink(symlinkPath, symlinkTarget()); - } catch (IOException ex) { - throw new UncheckedIOException(ex); - } - - List contentPaths; - if (COPY_IN_RESOURCES) { - contentPaths = List.of(appContentRoot); - } else if (basedir.equals(Path.of(""))) { - contentPaths = Stream.of(symlinkPath(), symlinkedPath()).map(path -> { - return path.getName(0); - }).map(appContentRoot::resolve).toList(); - } else { - contentPaths = List.of(appContentRoot.resolve(basedir)); - } - - return new Content() { - @Override - public List paths() { - return contentPaths; - } - - @Override - public Iterable verifiers(Path appContentRoot) { - return List.of( - new RegularFileVerifier(appContentRoot.resolve(symlinkedPath()), symlinkedPath), - new SymlinkTargetVerifier(appContentRoot.resolve(symlinkPath()), symlinkTarget()) - ); - } - }; - } - - @Override - public String toString() { - return String.format("symlink:[%s]->[%s][%s]", symlinkPath(), symlinkedPath(), symlinkTarget()); - } - - private Path symlinkPath() { - return basedir.resolve(symlink); - } - - private Path symlinkedPath() { - return basedir.resolve(symlinked); - } - - private Path symlinkTarget() { - return Optional.ofNullable(symlinkPath().getParent()).map(dir -> { - return dir.relativize(symlinkedPath()); - }).orElseGet(this::symlinkedPath); - } - } - - private static final class FileContentFactory implements ContentFactory { - - FileContentFactory(ThrowingSupplier factory, Path pathInAppContentRoot) { - this.factory = ThrowingSupplier.toSupplier(factory); - this.pathInAppContentRoot = pathInAppContentRoot; - if (pathInAppContentRoot.isAbsolute()) { - throw new IllegalArgumentException(); - } - } - - @Override - public Content create() { - Path srcPath = factory.get(); - if (!srcPath.endsWith(pathInAppContentRoot)) { - throw new IllegalArgumentException(); - } + private static Path createAppContentLink(Path appContentPath) throws IOException { + var appContentArg = TKit.createTempDirectory("app-content"); Path dstPath; - if (!COPY_IN_RESOURCES) { - dstPath = srcPath; + if (copyInResources) { + appContentArg = appContentArg.resolve(RESOURCES_DIR); + dstPath = appContentArg.resolve(LINKS_DIR) + .resolve(appContentPath.getFileName()); } else { - var contentDir = createAppContentRoot(); - dstPath = contentDir.resolve(pathInAppContentRoot); - try { - FileUtils.copyRecursive(srcPath, dstPath); - } catch (IOException ex) { - throw new UncheckedIOException(ex); + appContentArg = appContentArg.resolve(LINKS_DIR); + dstPath = appContentArg.resolve(appContentPath.getFileName()); + } + + Files.createDirectories(dstPath.getParent()); + + // Create target file for a link + String tagetName = dstPath.getFileName().toString().replace("Link", ""); + Path targetPath = dstPath.getParent().resolve(tagetName); + Files.write(targetPath, "foo".getBytes()); + // Create link + Files.createSymbolicLink(dstPath, targetPath.getFileName()); + + return appContentArg; + } + + private static List initAppContentPaths(List appContentPaths) { + return appContentPaths.stream().map(appContentPath -> { + if (appContentPath.endsWith(TEST_BAD)) { + return appContentPath; + } else if (isSymlinkPath(appContentPath)) { + return ThrowingFunction.toFunction( + AppContentInitializer::createAppContentLink).apply( + appContentPath); + } else if (copyInResources) { + return ThrowingFunction.toFunction( + AppContentInitializer::copyAppContentPath).apply( + appContentPath); + } else { + return TKit.TEST_SRC_ROOT.resolve(appContentPath); } - } - return new FileContent(dstPath, pathInAppContentRoot.getNameCount() - 1); - } - - @Override - public String toString() { - return pathInAppContentRoot.toString(); + }).toList(); } - private final Supplier factory; - private final Path pathInAppContentRoot; + private List jpackageArgs; + private final List> appContentPathGroups; } - - private static final ContentFactory TEST_JAVA = createTextFileContent("apps/PrintEnv.java", "Not what someone would expect"); - private static final ContentFactory TEST_DUKE = createTextFileContent("duke.txt", "Hi Duke!"); - private static final ContentFactory TEST_DIR = createDirTreeContent("apps"); - private static final ContentFactory TEST_BAD = new NonExistantPath(); - - // On OSX `--app-content` paths will be copied into the "Contents" folder - // of the output app image. - // "codesign" imposes restrictions on the directory structure of "Contents" folder. - // In particular, random files should be placed in "Contents/Resources" folder - // otherwise "codesign" will fail to sign. - // Need to prepare arguments for `--app-content` accordingly. - private static final boolean COPY_IN_RESOURCES = TKit.isOSX(); - - private static final Path RESOURCES_DIR = Path.of("Resources"); } diff --git a/test/jdk/tools/jpackage/share/AppImageFillOrderTest.java b/test/jdk/tools/jpackage/share/AppImageFillOrderTest.java deleted file mode 100644 index 75c0ddfc16f14..0000000000000 --- a/test/jdk/tools/jpackage/share/AppImageFillOrderTest.java +++ /dev/null @@ -1,359 +0,0 @@ -/* - * 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. - */ - -import static java.util.stream.Collectors.toMap; - -import java.io.IOException; -import java.io.UncheckedIOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Collection; -import java.util.List; -import java.util.Objects; -import java.util.Optional; -import java.util.TreeMap; -import java.util.function.BiFunction; -import java.util.function.Consumer; -import java.util.function.Function; -import java.util.stream.Stream; -import jdk.jpackage.test.Annotations.Parameter; -import jdk.jpackage.test.Annotations.ParameterSupplier; -import jdk.jpackage.test.Annotations.Test; -import jdk.jpackage.test.AppImageFile; -import jdk.jpackage.test.ApplicationLayout; -import jdk.jpackage.test.JPackageCommand; -import jdk.jpackage.test.TKit; - -/* - * @test - * @summary test order in which jpackage fills app image - * @library /test/jdk/tools/jpackage/helpers - * @build jdk.jpackage.test.* - * @compile -Xlint:all -Werror AppImageFillOrderTest.java - * @run main/othervm/timeout=1440 -Xmx512m - * jdk.jpackage.test.Main - * --jpt-run=AppImageFillOrderTest - */ - -/** - * Test order in which overlapping items are added to the app image. jpackage - * defaults should go first to let user-provided content override them. - * - *

    - * Custom content comes from: - *

      - *
    • input directory (--input) - *
    • app content (--app-content) - *
        - */ -public class AppImageFillOrderTest { - - @Test - @ParameterSupplier - public void test(AppImageOverlay overlays[]) { - test(createJPackage().setFakeRuntime(), overlays); - } - - /** - * Test they can override a file in the runtime. - * @param jlink - */ - @Test - @Parameter("true") - @Parameter("false") - public void testRuntime(boolean jlink) { - var cmd = createJPackage(); - if (jlink) { - cmd.ignoreDefaultRuntime(true); - } else { - // Configure fake runtime and create it. - cmd.setFakeRuntime().executePrerequisiteActions(); - - var runtimeDir = Path.of(cmd.getArgumentValue("--runtime-image")); - if (!runtimeDir.toAbsolutePath().normalize().startsWith(TKit.workDir().toAbsolutePath().normalize())) { - throw new IllegalStateException(String.format( - "Fake runtime [%s] created outside of the test work directory [%s]", - runtimeDir, TKit.workDir())); - } - - TKit.createTextFile(runtimeDir.resolve(RUNTIME_RELEASE_FILE), List.of("Foo release")); - } - - test(cmd, AppImageAppContentOverlay.APP_CONTENT_RUNTIME_RELEASE_FILE); - } - - /** - * Test they can not override .jpackage.xml file. - * @throws IOException - */ - @Test - public void testAppImageFile() throws IOException { - - var cmd = createJPackage().setFakeRuntime(); - - var outputBundle = cmd.outputBundle(); - - buildOverlay(cmd, TKit.createTempDirectory("app-content"), AppImageFile.getPathInAppImage(outputBundle)) - .textContent("This is not a valid XML content") - .configureCmdOptions().createOverlayFile(); - - // Run jpackage and verify it created valid .jpackage.xml file ignoring the overlay. - cmd.executeAndAssertImageCreated(); - - TKit.trace(String.format("Parse [%s] file...", AppImageFile.getPathInAppImage(outputBundle))); - AppImageFile.load(outputBundle); - } - - private static void test(JPackageCommand cmd, AppImageOverlay... overlays) { - if (overlays.length == 0) { - throw new IllegalArgumentException(); - } - - final var outputDir = Path.of(cmd.getArgumentValue("--dest")); - final var noOverlaysOutputDir = Path.of(outputDir.toString() + "-no-overlay"); - cmd.setArgumentValue("--dest", noOverlaysOutputDir); - - // Run the command without overlays with redirected output directory. - cmd.execute(); - - final Optional appContentRoot; - if (Stream.of(overlays).anyMatch(AppImageAppContentOverlay.class::isInstance)) { - appContentRoot = Optional.of(TKit.createTempDirectory("app-content")); - } else { - appContentRoot = Optional.empty(); - } - - // Apply overlays to the command. - var fileCopies = Stream.of(overlays).map(overlay -> { - switch (overlay) { - case AppImageDefaultOverlay v -> { - return v.addOverlay(cmd); - } - case AppImageAppContentOverlay v -> { - return v.addOverlay(cmd, appContentRoot.orElseThrow()); - } - } - }).flatMap(Collection::stream).collect(toMap(FileCopy::out, x -> x, (a, b) -> { - return b; - }, TreeMap::new)).values().stream().toList(); - - // Collect paths in the app image that will be affected by overlays. - var noOverlayOutputPaths = fileCopies.stream().map(FileCopy::out).toList(); - - fileCopies = fileCopies.stream().map(v -> { - return new FileCopy(v.in(), outputDir.resolve(noOverlaysOutputDir.relativize(v.out()))); - }).toList(); - - // Restore the original output directory for the command and execute it. - cmd.setArgumentValue("--dest", outputDir).execute(); - - for (var i = 0; i != fileCopies.size(); i++) { - var noOverlayPath = noOverlayOutputPaths.get(i); - var fc = fileCopies.get(i); - TKit.assertSameFileContent(fc.in(), fc.out()); - TKit.assertMismatchFileContent(noOverlayPath, fc.out()); - } - } - - public static Collection test() { - return Stream.of( - - // Overwrite main launcher .cfg file from the input dir. - List.of(AppImageDefaultOverlay.INPUT_MAIN_LAUNCHER_CFG), - - // Overwrite main launcher .cfg file from the app content dir. - List.of(AppImageAppContentOverlay.APP_CONTENT_MAIN_LAUNCHER_CFG), - - // Overwrite main launcher .cfg file from the input dir and from the app content dir. - // The one from app content should win. - List.of( - AppImageDefaultOverlay.INPUT_MAIN_LAUNCHER_CFG, - AppImageAppContentOverlay.APP_CONTENT_MAIN_LAUNCHER_CFG - ), - - // Overwrite main jar from the app content dir. - List.of(AppImageAppContentOverlay.APP_CONTENT_MAIN_JAR) - ).map(args -> { - return args.toArray(AppImageOverlay[]::new); - }).map(args -> { - return new Object[] {args}; - }).toList(); - } - - - public sealed interface AppImageOverlay { - } - - - private enum AppImageDefaultOverlay implements AppImageOverlay { - INPUT_MAIN_LAUNCHER_CFG(AppImageFillOrderTest::replaceMainLauncherCfgFile), - ; - - AppImageDefaultOverlay(Function func) { - Objects.requireNonNull(func); - this.func = cmd -> { - return List.of(func.apply(cmd)); - }; - } - - Collection addOverlay(JPackageCommand cmd) { - return func.apply(cmd); - } - - private final Function> func; - } - - - private enum AppImageAppContentOverlay implements AppImageOverlay { - // Replace the standard main launcher .cfg file with the custom one from the app content. - APP_CONTENT_MAIN_LAUNCHER_CFG((cmd, appContentRoot) -> { - return buildOverlay(cmd, appContentRoot, cmd.appLauncherCfgPath(null)) - .textContent("!Olleh") - .configureCmdOptions().createOverlayFile(); - }), - - // Replace the jar file that jpackage will pick up from the input directory with the custom one. - APP_CONTENT_MAIN_JAR((cmd, appContentRoot) -> { - return buildOverlay(cmd, appContentRoot, cmd.appLayout().appDirectory().resolve(cmd.getArgumentValue("--main-jar"))) - .textContent("Surprise!") - .configureCmdOptions().createOverlayFile(); - }), - - // Replace "release" file in the runtime directory. - APP_CONTENT_RUNTIME_RELEASE_FILE((cmd, appContentRoot) -> { - return buildOverlay(cmd, appContentRoot, cmd.appLayout().runtimeHomeDirectory().resolve("release")) - .textContent("blob") - .configureCmdOptions().createOverlayFile(); - }), - ; - - AppImageAppContentOverlay(BiFunction func) { - Objects.requireNonNull(func); - this.func = (cmd, appContentRoot) -> { - return List.of(func.apply(cmd, appContentRoot)); - }; - } - - Collection addOverlay(JPackageCommand cmd, Path appContentRoot) { - return func.apply(cmd, appContentRoot); - } - - private final BiFunction> func; - } - - - private record FileCopy(Path in, Path out) { - FileCopy { - Objects.requireNonNull(in); - Objects.requireNonNull(out); - } - } - - - private static FileCopy replaceMainLauncherCfgFile(JPackageCommand cmd) { - // Replace the standard main launcher .cfg file with the custom one from the input dir. - final var outputFile = cmd.appLauncherCfgPath(null); - - final var inputDir = Path.of(cmd.getArgumentValue("--input")); - - final var file = inputDir.resolve(outputFile.getFileName()); - - TKit.createTextFile(file, List.of("Hello!")); - - return new FileCopy(file, outputFile); - } - - private static AppContentOverlayFileBuilder buildOverlay(JPackageCommand cmd, Path appContentRoot, Path outputFile) { - return new AppContentOverlayFileBuilder(cmd, appContentRoot, outputFile); - } - - - private static final class AppContentOverlayFileBuilder { - - AppContentOverlayFileBuilder(JPackageCommand cmd, Path appContentRoot, Path outputFile) { - if (outputFile.isAbsolute()) { - throw new IllegalArgumentException(); - } - - if (!outputFile.startsWith(cmd.outputBundle())) { - throw new IllegalArgumentException(); - } - - this.cmd = Objects.requireNonNull(cmd); - this.outputFile = Objects.requireNonNull(outputFile); - this.appContentRoot = Objects.requireNonNull(appContentRoot); - } - - FileCopy createOverlayFile() { - final var file = appContentRoot.resolve(pathInAppContentDirectory()); - - try { - Files.createDirectories(file.getParent()); - } catch (IOException ex) { - throw new UncheckedIOException(ex); - } - fileContentInitializer.accept(file); - - return new FileCopy(file, outputFile); - } - - AppContentOverlayFileBuilder configureCmdOptions() { - cmd.addArguments("--app-content", appContentRoot.resolve(pathInAppContentDirectory().getName(0))); - return this; - } - - AppContentOverlayFileBuilder content(Consumer v) { - fileContentInitializer = v; - return this; - } - - AppContentOverlayFileBuilder textContent(String... lines) { - return content(path -> { - TKit.createTextFile(path, List.of(lines)); - }); - } - - private Path pathInAppContentDirectory() { - return APP_IMAGE_LAYOUT.resolveAt(cmd.outputBundle()).contentDirectory().relativize(outputFile); - } - - private Consumer fileContentInitializer; - private final JPackageCommand cmd; - private final Path outputFile; - private final Path appContentRoot; - } - - - private static JPackageCommand createJPackage() { - // With short name. - var cmd = JPackageCommand.helloAppImage().setArgumentValue("--name", "Foo"); - - // Clean leftovers in the input dir from the previous test run if any. - TKit.deleteDirectoryContentsRecursive(cmd.inputDir()); - - return cmd; - } - - private static final ApplicationLayout APP_IMAGE_LAYOUT = ApplicationLayout.platformAppImage(); - private static final Path RUNTIME_RELEASE_FILE = Path.of("release"); -} diff --git a/test/jdk/tools/jpackage/share/AppImagePackageTest.java b/test/jdk/tools/jpackage/share/AppImagePackageTest.java index aacb76b122b29..34a418c6f9ec9 100644 --- a/test/jdk/tools/jpackage/share/AppImagePackageTest.java +++ b/test/jdk/tools/jpackage/share/AppImagePackageTest.java @@ -21,21 +21,20 @@ * questions. */ -import java.io.IOException; -import java.nio.file.Files; import java.nio.file.Path; -import java.util.function.Predicate; +import java.nio.file.Files; +import java.io.IOException; +import java.util.List; import jdk.jpackage.internal.util.XmlUtils; -import jdk.jpackage.test.Annotations.Parameter; -import jdk.jpackage.test.Annotations.Test; import jdk.jpackage.test.AppImageFile; +import jdk.jpackage.test.Annotations.Parameter; import jdk.jpackage.test.CannedFormattedString; +import jdk.jpackage.test.TKit; import jdk.jpackage.test.JPackageCommand; -import jdk.jpackage.test.JPackageCommand.StandardAssert; import jdk.jpackage.test.JPackageStringBundle; import jdk.jpackage.test.PackageTest; import jdk.jpackage.test.RunnablePackageTest.Action; -import jdk.jpackage.test.TKit; +import jdk.jpackage.test.Annotations.Test; /** * Test --app-image parameter. The output installer should provide the same @@ -56,86 +55,56 @@ */ public class AppImagePackageTest { - /** - * Create a native bundle from a valid predefined app image produced by jpackage. - */ @Test public static void test() { + Path appimageOutput = TKit.workDir().resolve("appimage"); - var appImageCmd = JPackageCommand.helloAppImage() - .setArgumentValue("--dest", TKit.createTempDirectory("appimage")); + JPackageCommand appImageCmd = JPackageCommand.helloAppImage() + .setArgumentValue("--dest", appimageOutput); new PackageTest() - .addRunOnceInitializer(appImageCmd::execute) + .addRunOnceInitializer(() -> appImageCmd.execute()) .addInitializer(cmd -> { cmd.addArguments("--app-image", appImageCmd.outputBundle()); cmd.removeArgumentWithValue("--input"); }).addBundleDesktopIntegrationVerifier(false).run(); } - /** - * Create a native bundle from a predefined app image not produced by jpackage - * but having a valid ".jpackage.xml" file. - * - * @param withIcon {@code true} if jpackage command line should have "--icon" - * option - */ @Test @Parameter("true") @Parameter("false") public static void testEmpty(boolean withIcon) throws IOException { + final String name = "EmptyAppImagePackageTest"; + final String imageName = name + (TKit.isOSX() ? ".app" : ""); + Path appImageDir = TKit.createTempDirectory("appimage").resolve(imageName); - var appImageCmd = JPackageCommand.helloAppImage() - .setFakeRuntime() - .setArgumentValue("--name", "EmptyAppImagePackageTest") - .setArgumentValue("--dest", TKit.createTempDirectory("appimage")); + Files.createDirectories(appImageDir.resolve("bin")); + Path libDir = Files.createDirectories(appImageDir.resolve("lib")); + TKit.createTextFile(libDir.resolve("README"), + List.of("This is some arbitrary text for the README file\n")); new PackageTest() - .addRunOnceInitializer(appImageCmd::execute) - .addRunOnceInitializer(() -> { - var layout = appImageCmd.appLayout(); - if (!TKit.isOSX()) { - // Delete the launcher if not on macOS. - // On macOS, deleting the launcher will render the app bundle invalid. - TKit.deleteIfExists(appImageCmd.appLauncherPath()); - } - // Delete the runtime. - TKit.deleteDirectoryRecursive(layout.runtimeDirectory()); - // Delete the "app" dir. - TKit.deleteDirectoryRecursive(layout.appDirectory()); - - new AppImageFile(appImageCmd.name(), "PhonyMainClass").save(appImageCmd.outputBundle()); - var appImageDir = appImageCmd.outputBundle(); - - TKit.trace(String.format("Files in [%s] app image:", appImageDir)); - try (var files = Files.walk(appImageDir)) { - files.sequential() - .filter(Predicate.isEqual(appImageDir).negate()) - .map(path -> String.format("[%s]", appImageDir.relativize(path))) - .forEachOrdered(TKit::trace); - TKit.trace("Done"); - } - }) .addInitializer(cmd -> { - cmd.addArguments("--app-image", appImageCmd.outputBundle()); + cmd.addArguments("--app-image", appImageDir); if (withIcon) { cmd.addArguments("--icon", iconPath("icon")); } cmd.removeArgumentWithValue("--input"); + new AppImageFile("EmptyAppImagePackageTest", "Hello").save(appImageDir); - cmd.excludeStandardAsserts( - StandardAssert.MAIN_JAR_FILE, - StandardAssert.MAIN_LAUNCHER_FILES, - StandardAssert.MAC_BUNDLE_STRUCTURE, - StandardAssert.RUNTIME_DIRECTORY); + // on mac, with --app-image and without --mac-package-identifier, + // will try to infer it from the image, so foreign image needs it. + if (TKit.isOSX()) { + cmd.addArguments("--mac-package-identifier", name); + } }) - .run(Action.CREATE_AND_UNPACK); + // On macOS we always signing app image and signing will fail, since + // test produces invalid app bundle. + .setExpectedExitCode(TKit.isOSX() ? 1 : 0) + .run(Action.CREATE, Action.UNPACK); + // default: {CREATE, UNPACK, VERIFY}, but we can't verify foreign image } - /** - * Bad predefined app image - not an output of jpackage. - * jpackage command using the bad predefined app image doesn't have "--name" option. - */ @Test public static void testBadAppImage() throws IOException { Path appImageDir = TKit.createTempDirectory("appimage"); @@ -145,9 +114,6 @@ public static void testBadAppImage() throws IOException { }).run(Action.CREATE); } - /** - * Bad predefined app image - not an output of jpackage. - */ @Test public static void testBadAppImage2() throws IOException { Path appImageDir = TKit.createTempDirectory("appimage"); @@ -155,11 +121,8 @@ public static void testBadAppImage2() throws IOException { configureBadAppImage(appImageDir).run(Action.CREATE); } - /** - * Bad predefined app image - valid app image missing ".jpackage.xml" file. - */ @Test - public static void testBadAppImage3() { + public static void testBadAppImage3() throws IOException { Path appImageDir = TKit.createTempDirectory("appimage"); JPackageCommand appImageCmd = JPackageCommand.helloAppImage(). @@ -171,11 +134,8 @@ public static void testBadAppImage3() { }).run(Action.CREATE); } - /** - * Bad predefined app image - valid app image with invalid ".jpackage.xml" file. - */ @Test - public static void testBadAppImageFile() { + public static void testBadAppImageFile() throws IOException { final var appImageRoot = TKit.createTempDirectory("appimage"); final var appImageCmd = JPackageCommand.helloAppImage(). diff --git a/test/jdk/tools/jpackage/share/FileAssociationsTest.java b/test/jdk/tools/jpackage/share/FileAssociationsTest.java index cd4a049153241..2257c5dbc6510 100644 --- a/test/jdk/tools/jpackage/share/FileAssociationsTest.java +++ b/test/jdk/tools/jpackage/share/FileAssociationsTest.java @@ -21,13 +21,10 @@ * questions. */ -import static java.util.Map.entry; import static jdk.jpackage.test.JPackageStringBundle.MAIN; import java.nio.file.Path; -import java.util.List; import java.util.Map; -import java.util.TreeMap; import jdk.jpackage.test.Annotations.Parameter; import jdk.jpackage.test.Annotations.Test; import jdk.jpackage.test.FileAssociations; @@ -117,9 +114,9 @@ public static void testNoMime() { final Path propFile = TKit.workDir().resolve("fa.properties"); initPackageTest().addRunOnceInitializer(() -> { - TKit.createPropertiesFile(propFile, List.of( - entry("extension", "foo"), - entry("description", "bar") + TKit.createPropertiesFile(propFile, Map.of( + "extension", "foo", + "description", "bar" )); }).addInitializer(cmd -> { cmd.addArguments("--file-associations", propFile); @@ -134,10 +131,10 @@ public static void testTooManyMimes() { final Path propFile = TKit.workDir().resolve("fa.properties"); initPackageTest().addRunOnceInitializer(() -> { - TKit.createPropertiesFile(propFile, List.of( - entry("mime-type", "application/x-jpackage-foo, application/x-jpackage-bar"), - entry("extension", "foo"), - entry("description", "bar") + TKit.createPropertiesFile(propFile, Map.of( + "mime-type", "application/x-jpackage-foo, application/x-jpackage-bar", + "extension", "foo", + "description", "bar" )); }).addInitializer(cmd -> { cmd.addArguments("--file-associations", propFile); diff --git a/test/jdk/tools/jpackage/share/IconTest.java b/test/jdk/tools/jpackage/share/IconTest.java index 03726e524dc36..a2a9e67bd9101 100644 --- a/test/jdk/tools/jpackage/share/IconTest.java +++ b/test/jdk/tools/jpackage/share/IconTest.java @@ -21,10 +21,10 @@ * questions. */ -import static jdk.jpackage.test.AdditionalLauncher.getAdditionalLauncherProperties; - import java.io.IOException; -import java.io.UncheckedIOException; +import java.util.stream.Stream; +import java.util.stream.Collectors; +import java.util.function.Consumer; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.StandardCopyOption; @@ -32,26 +32,19 @@ import java.util.Collection; import java.util.List; import java.util.Map; -import java.util.Objects; import java.util.Optional; import java.util.Set; -import java.util.TreeMap; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import jdk.jpackage.internal.util.function.ThrowingBiConsumer; -import jdk.jpackage.internal.util.function.ThrowingConsumer; -import jdk.jpackage.test.AdditionalLauncher; -import jdk.jpackage.test.Annotations.Parameters; -import jdk.jpackage.test.Annotations.Test; -import jdk.jpackage.test.CannedFormattedString; -import jdk.jpackage.test.ConfigurationTarget; -import jdk.jpackage.test.Executor; +import jdk.jpackage.test.TKit; import jdk.jpackage.test.JPackageCommand; -import jdk.jpackage.test.JPackageStringBundle; import jdk.jpackage.test.LauncherIconVerifier; -import jdk.jpackage.test.LinuxHelper; import jdk.jpackage.test.PackageTest; -import jdk.jpackage.test.TKit; +import jdk.jpackage.test.Executor; +import jdk.jpackage.test.LinuxHelper; +import jdk.jpackage.test.AdditionalLauncher; +import jdk.jpackage.internal.util.function.ThrowingConsumer; +import jdk.jpackage.internal.util.function.ThrowingBiConsumer; +import jdk.jpackage.test.Annotations.Parameters; +import jdk.jpackage.test.Annotations.Test; /* * @test @@ -99,18 +92,18 @@ public IconTest(BundleType bundleType, IconType mainLauncherIconType, IconType additionalLauncherIconType, String[] extraJPackageArgs) { this.appImage = (bundleType == BundleType.AppImage); this.extraJPackageArgs = extraJPackageArgs; - config = new TreeMap<>(Map.of( + config = Map.of( Launcher.Main, mainLauncherIconType, - Launcher.Additional, additionalLauncherIconType)); + Launcher.Additional, additionalLauncherIconType); } public IconTest(BundleType bundleType, IconType mainLauncherIconType, IconType additionalLauncherIconType) { this.appImage = (bundleType == BundleType.AppImage); this.extraJPackageArgs = new String[0]; - config = new TreeMap<>(Map.of( + config = Map.of( Launcher.Main, mainLauncherIconType, - Launcher.Additional, additionalLauncherIconType)); + Launcher.Additional, additionalLauncherIconType); } public IconTest(BundleType bundleType, IconType mainLauncherIconType) { @@ -165,37 +158,27 @@ public static Collection data() { @Test public void test() throws IOException { - - final ConfigurationTarget target; if (appImage) { - target = new ConfigurationTarget(JPackageCommand.helloAppImage()); + JPackageCommand cmd = initAppImageTest(); + var result = cmd.executeAndAssertImageCreated(); + ThrowingConsumer.toConsumer(createInstallVerifier()).accept(cmd); + ThrowingBiConsumer.toBiConsumer(createBundleVerifier()).accept(cmd, result); } else { - target = new ConfigurationTarget(new PackageTest().configureHelloApp()); - } - - initTest(target); - - var installVerifier = createInstallVerifier(); - var bundleVerifier = createBundleVerifier(); + PackageTest test = initPackageTest(); + test.addInstallVerifier(createInstallVerifier()); + test.addBundleVerifier(createBundleVerifier()); - var cmdResult = target.cmd().map(JPackageCommand::executeAndAssertImageCreated); - - target.apply(ThrowingConsumer.toConsumer(installVerifier), test -> { - test.addInstallVerifier(installVerifier); - }).apply(cmd -> { - ThrowingBiConsumer.toBiConsumer(bundleVerifier).accept(cmd, cmdResult.orElseThrow()); - }, test -> { - test.addBundleVerifier(bundleVerifier); test.addBundleDesktopIntegrationVerifier(config.values().stream() .anyMatch(this::isWithDesktopIntegration)); - }); - target.test().ifPresent(v -> { - v.run(PackageTest.Action.CREATE_AND_UNPACK); - }); + test.run(PackageTest.Action.CREATE_AND_UNPACK); + } } boolean isWithDesktopIntegration(IconType iconType) { + if (appImage) { + return false; + } boolean withDesktopFile = !Set.of( IconType.NoIcon, IconType.DefaultIcon).contains(iconType); @@ -205,110 +188,89 @@ boolean isWithDesktopIntegration(IconType iconType) { private ThrowingBiConsumer createBundleVerifier() { return (cmd, result) -> { - Stream.of(Launcher.Main, Launcher.Additional).filter(config::containsKey).forEach(launcher -> { - createConsoleOutputVerifier(cmd, launcher).ifPresent(verifier -> { + var verifier = createConsoleOutputVerifier(cmd.name(), config.get( + Launcher.Main), null); + if (verifier != null) { + verifier.apply(result.getOutput()); + } + + if (config.containsKey(Launcher.Additional)) { + verifier = createConsoleOutputVerifier( + Launcher.Additional.launcherName, config.get( + Launcher.Additional), config.get(Launcher.Main)); + if (verifier != null) { verifier.apply(result.getOutput()); - }); - }); + } + } }; } - private Optional createConsoleOutputVerifier( - JPackageCommand cmd, Launcher launcher) { - - var launcherName = Optional.ofNullable(launcher.launcherName).orElseGet(cmd::name); - var resourceName = launcherName; - Optional customIcon; - - if (launcherName.equals(cmd.name())) { - customIcon = Optional.ofNullable(cmd.getArgumentValue("--icon")).map(Path::of); - } else if (config.get(launcher) == IconType.DefaultIcon) { - resourceName = cmd.name(); - customIcon = Optional.ofNullable(cmd.getArgumentValue("--icon")).map(Path::of); - } else { - customIcon = getAdditionalLauncherProperties(cmd, launcherName).findProperty("icon").map(Path::of); + private TKit.TextStreamVerifier createConsoleOutputVerifier( + String launcherName, IconType iconType, IconType mainIconType) { + if (iconType == IconType.DefaultIcon && mainIconType != null) { + iconType = mainIconType; } - - return createConsoleOutputVerifier( - getBundleIconType(cmd, launcher), - launcherName, - resourceName, - customIcon); + return createConsoleOutputVerifier(launcherName, iconType); } - private static Optional createConsoleOutputVerifier( - IconType iconType, String launcherName, String resourceName, Optional customIcon) { - - Objects.requireNonNull(launcherName); - Objects.requireNonNull(resourceName); - Objects.requireNonNull(customIcon); - - CannedFormattedString lookupString; - + private static TKit.TextStreamVerifier createConsoleOutputVerifier( + String launcherName, IconType iconType) { + String lookupString = null; switch (iconType) { case DefaultIcon: - lookupString = JPackageStringBundle.MAIN.cannedFormattedString( - "message.using-default-resource", + lookupString = String.format( + "Using default package resource %s [icon] (add %s%s to the resource-dir to customize)", "JavaApp" + TKit.ICON_SUFFIX, - "[icon]", - launcherName + TKit.ICON_SUFFIX); + launcherName, TKit.ICON_SUFFIX); break; case ResourceDirIcon: - lookupString = JPackageStringBundle.MAIN.cannedFormattedString( - "message.using-custom-resource", - "[icon]", - resourceName + TKit.ICON_SUFFIX); + lookupString = String.format( + "Using custom package resource [icon] (loaded from %s%s)", + launcherName, TKit.ICON_SUFFIX); break; case CustomIcon: case CustomWithResourceDirIcon: - lookupString = JPackageStringBundle.MAIN.cannedFormattedString( - "message.using-custom-resource-from-file", - "[icon]", - customIcon.orElseThrow()); + lookupString = "Using custom package resource [icon] (loaded from file"; break; default: - return Optional.empty(); + return null; } - return Optional.of(TKit.assertTextStream(lookupString.getValue())); + return TKit.assertTextStream(lookupString); } private ThrowingConsumer createInstallVerifier() { - return cmd -> { - var verifier = new LauncherIconVerifier(); - - var bundleIconType = getBundleIconType(cmd, Launcher.Main); - - switch (bundleIconType) { - case NoIcon: - verifier.setExpectedNoIcon(); - break; + LauncherIconVerifier verifier = new LauncherIconVerifier(); + switch (config.get(Launcher.Main)) { + case NoIcon: + verifier.setExpectedIcon(null); + break; - case DefaultIcon: - verifier.setExpectedDefaultIcon(); - break; + case DefaultIcon: + verifier.setExpectedDefaultIcon(); + break; - case CustomIcon: - verifier.setExpectedIcon(Launcher.Main.cmdlineIcon); - break; + case CustomIcon: + verifier.setExpectedIcon(Launcher.Main.cmdlineIcon); + break; - case ResourceDirIcon: - verifier.setExpectedIcon(Launcher.Main.resourceDirIcon); - break; + case ResourceDirIcon: + verifier.setExpectedIcon(Launcher.Main.resourceDirIcon); + break; - case CustomWithResourceDirIcon: - verifier.setExpectedIcon(Launcher.Main2.cmdlineIcon); - break; - } + case CustomWithResourceDirIcon: + verifier.setExpectedIcon(Launcher.Main2.cmdlineIcon); + break; + } + return cmd -> { verifier.applyTo(cmd); - if (TKit.isLinux() && !cmd.isImagePackageType()) { Path desktopFile = LinuxHelper.getDesktopFile(cmd); - if (isWithDesktopIntegration(bundleIconType)) { + if (isWithDesktopIntegration(config.get(Launcher.Main))) { TKit.assertFileExists(desktopFile); } else { TKit.assertPathExists(desktopFile, false); @@ -317,61 +279,80 @@ private ThrowingConsumer createInstallVerifier() { }; } - private void initTest(ConfigurationTarget target) { + private void initTest(JPackageCommand cmd, PackageTest test) { config.entrySet().forEach(ThrowingConsumer.toConsumer(entry -> { - initTest(entry.getKey(), entry.getValue(), target); + initTest(entry.getKey(), entry.getValue(), cmd, test); })); - target.addInitializer(cmd -> { - cmd.saveConsoleOutput(true); - cmd.setFakeRuntime(); - cmd.addArguments(extraJPackageArgs); - }); + ThrowingConsumer initializer = testCmd -> { + testCmd.saveConsoleOutput(true); + testCmd.setFakeRuntime(); + testCmd.addArguments(extraJPackageArgs); + }; + + if (test != null) { + test.addInitializer(initializer); + } else { + ThrowingConsumer.toConsumer(initializer).accept(cmd); + } } private static void initTest(Launcher cfg, IconType iconType, - ConfigurationTarget target) throws IOException { + JPackageCommand cmd, PackageTest test) throws IOException { + Consumer addLauncher = v -> { + if (test != null) { + v.applyTo(test); + } else { + v.applyTo(cmd); + } + }; switch (iconType) { case DefaultIcon: - Optional.ofNullable(cfg.launcherName).map(AdditionalLauncher::new) - .ifPresent(target::add); + if (cfg.launcherName != null) { + addLauncher.accept(new AdditionalLauncher(cfg.launcherName)); + } break; case NoIcon: - Optional.ofNullable(cfg.launcherName).map(AdditionalLauncher::new) - .map(AdditionalLauncher::setNoIcon) - .ifPresent(target::add); + if (cfg.launcherName != null) { + addLauncher.accept( + new AdditionalLauncher(cfg.launcherName).setNoIcon()); + } break; case CustomIcon: - addCustomIcon(target, cfg.launcherName, cfg.cmdlineIcon); + if (test != null) { + addCustomIcon(null, test, cfg.launcherName, cfg.cmdlineIcon); + } else { + addCustomIcon(cmd, null, cfg.launcherName, cfg.cmdlineIcon); + } break; case ResourceDirIcon: - if (Launcher.PRIMARY.contains(cfg)) { - Optional.ofNullable(cfg.launcherName).map(AdditionalLauncher::new) - .ifPresent(target::add); + if (Launcher.PRIMARY.contains(cfg) && cfg.launcherName != null) { + addLauncher.accept(new AdditionalLauncher(cfg.launcherName)); + } + if (test != null) { + test.addInitializer(testCmd -> { + addResourceDirIcon(testCmd, cfg.launcherName, + cfg.resourceDirIcon); + }); + } else { + addResourceDirIcon(cmd, cfg.launcherName, cfg.resourceDirIcon); } - target.addInitializer(cmd -> { - try { - addResourceDirIcon(cmd, cfg.launcherName, cfg.resourceDirIcon); - } catch (IOException ex) { - throw new UncheckedIOException(ex); - } - }); break; case CustomWithResourceDirIcon: switch (cfg) { case Main: - initTest(Launcher.Main2, IconType.CustomIcon, target); - initTest(Launcher.Main2, IconType.ResourceDirIcon, target); + initTest(Launcher.Main2, IconType.CustomIcon, cmd, test); + initTest(Launcher.Main2, IconType.ResourceDirIcon, cmd, test); break; case Additional: - initTest(Launcher.Additional2, IconType.CustomIcon, target); - initTest(Launcher.Additional2, IconType.ResourceDirIcon, target); + initTest(Launcher.Additional2, IconType.CustomIcon, cmd, test); + initTest(Launcher.Additional2, IconType.ResourceDirIcon, cmd, test); break; default: @@ -381,46 +362,29 @@ private static void initTest(Launcher cfg, IconType iconType, } } - private IconType getBundleIconType(JPackageCommand cmd, Launcher launcher) { - return getBundleIconType(cmd, config.get(Launcher.Main), launcher, config.get(launcher)); + private JPackageCommand initAppImageTest() { + JPackageCommand cmd = JPackageCommand.helloAppImage(); + initTest(cmd, null); + return cmd; } - /** - * Returns the expected icon type of the given launcher in the output bundle - * that the given jpackage command line will output based on the icon type - * configured for the launcher. - * - * @param cmd jpackage command line - * @param mainLauncherIconType the icon type configured for the main launcher - * @param launcher the launcher - * @param iconType the icon type configured for the specified - * launcher - * @return the type of of an icon of the given launcher in the output bundle - */ - private static IconType getBundleIconType(JPackageCommand cmd, - IconType mainLauncherIconType, Launcher launcher, IconType iconType) { - - Objects.requireNonNull(cmd); - Objects.requireNonNull(mainLauncherIconType); - Objects.requireNonNull(launcher); - Objects.requireNonNull(iconType); - - if (iconType == IconType.DefaultIcon) { - iconType = mainLauncherIconType; - } - - return iconType; + private PackageTest initPackageTest() { + PackageTest test = new PackageTest().configureHelloApp(); + initTest(null, test); + return test; } private static void addResourceDirIcon(JPackageCommand cmd, String launcherName, Path iconPath) throws IOException { - var resourceDir = Optional.ofNullable(cmd.getArgumentValue("--resource-dir")).map(Path::of).orElseGet(() -> { - return TKit.createTempDirectory("resources"); - }); - - cmd.addArguments("--resource-dir", resourceDir); + Path resourceDir = cmd.getArgumentValue("--resource-dir", () -> null, + Path::of); + if (resourceDir == null) { + resourceDir = TKit.createTempDirectory("resources"); + cmd.addArguments("--resource-dir", resourceDir); + } - String dstIconFileName = Optional.ofNullable(launcherName).orElseGet(cmd::name) + TKit.ICON_SUFFIX; + String dstIconFileName = Optional.ofNullable(launcherName).orElseGet( + () -> cmd.name()) + TKit.ICON_SUFFIX; TKit.trace(String.format("Resource file: [%s] <- [%s]", resourceDir.resolve(dstIconFileName), iconPath)); @@ -428,16 +392,23 @@ private static void addResourceDirIcon(JPackageCommand cmd, StandardCopyOption.REPLACE_EXISTING); } - private static void addCustomIcon(ConfigurationTarget target, - String launcherName, Path iconPath) { + private static void addCustomIcon(JPackageCommand cmd, PackageTest test, + String launcherName, Path iconPath) throws IOException { if (launcherName != null) { - var al = new AdditionalLauncher(launcherName).setIcon(iconPath); - target.apply(al::applyTo, al::applyTo); - } else { - target.addInitializer(cmd -> { - cmd.addArguments("--icon", iconPath); + AdditionalLauncher al = new AdditionalLauncher(launcherName).setIcon( + iconPath); + if (test != null) { + al.applyTo(test); + } else { + al.applyTo(cmd); + } + } else if (test != null) { + test.addInitializer(testCmd -> { + testCmd.addArguments("--icon", iconPath); }); + } else { + cmd.addArguments("--icon", iconPath); } } diff --git a/test/jdk/tools/jpackage/share/InOutPathTest.java b/test/jdk/tools/jpackage/share/InOutPathTest.java index d36731c2960e5..f7c597d2ed346 100644 --- a/test/jdk/tools/jpackage/share/InOutPathTest.java +++ b/test/jdk/tools/jpackage/share/InOutPathTest.java @@ -38,7 +38,7 @@ import jdk.jpackage.test.Annotations.Test; import jdk.jpackage.internal.util.function.ThrowingConsumer; import jdk.jpackage.test.JPackageCommand; -import jdk.jpackage.test.JPackageCommand.StandardAssert; +import jdk.jpackage.test.JPackageCommand.AppLayoutAssert; import jdk.jpackage.test.PackageTest; import jdk.jpackage.test.PackageType; import static jdk.jpackage.test.RunnablePackageTest.Action.CREATE_AND_UNPACK; @@ -177,7 +177,7 @@ private static void runTest(Set packageTypes, if (!isAppImageValid(cmd)) { // Standard asserts for .jpackage.xml fail in messed up app image. Disable them. // Other standard asserts for app image contents should pass. - cmd.excludeStandardAsserts(StandardAssert.APP_IMAGE_FILE); + cmd.excludeAppLayoutAsserts(AppLayoutAssert.APP_IMAGE_FILE); } }; diff --git a/test/jdk/tools/jpackage/share/LicenseTest.java b/test/jdk/tools/jpackage/share/LicenseTest.java index 1c6bfd51b62d6..c9e3c8508aa61 100644 --- a/test/jdk/tools/jpackage/share/LicenseTest.java +++ b/test/jdk/tools/jpackage/share/LicenseTest.java @@ -208,7 +208,7 @@ private static Path linuxLicenseFile(JPackageCommand cmd) { private static void verifyLicenseFileInLinuxPackage(JPackageCommand cmd, Path expectedLicensePath) { TKit.assertTrue(LinuxHelper.getPackageFiles(cmd).filter(path -> path.equals( - expectedLicensePath)).findFirst().isPresent(), + expectedLicensePath)).findFirst().orElse(null) != null, String.format("Check license file [%s] is in %s package", expectedLicensePath, LinuxHelper.getPackageName(cmd))); } diff --git a/test/jdk/tools/jpackage/share/RuntimePackageTest.java b/test/jdk/tools/jpackage/share/RuntimePackageTest.java index caa129713b48b..f66f774b227ac 100644 --- a/test/jdk/tools/jpackage/share/RuntimePackageTest.java +++ b/test/jdk/tools/jpackage/share/RuntimePackageTest.java @@ -135,7 +135,11 @@ private static PackageTest init(ThrowingSupplier createRuntime) { }) .addInstallVerifier(cmd -> { var src = TKit.assertDirectoryContentRecursive(inputRuntimeDir(cmd)).items(); - var dest = cmd.appLayout().runtimeHomeDirectory(); + Path dest = cmd.appRuntimeDirectory(); + if (TKit.isOSX()) { + dest = dest.resolve("Contents/Home"); + } + TKit.assertDirectoryContentRecursive(dest).match(src); }) .forTypes(PackageType.LINUX_DEB, test -> { diff --git a/test/jdk/tools/jpackage/windows/WinNoRestartTest.java b/test/jdk/tools/jpackage/windows/WinNoRestartTest.java index 909ee06b01a12..7f04ee2bd2ef3 100644 --- a/test/jdk/tools/jpackage/windows/WinNoRestartTest.java +++ b/test/jdk/tools/jpackage/windows/WinNoRestartTest.java @@ -21,15 +21,16 @@ * questions. */ -import static jdk.jpackage.test.WindowsHelper.killAppLauncherProcess; - import java.io.IOException; import java.time.Duration; import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import jdk.jpackage.test.JPackageCommand; import jdk.jpackage.test.Annotations.Test; import jdk.jpackage.test.CfgFile; import jdk.jpackage.test.HelloApp; -import jdk.jpackage.test.JPackageCommand; +import static jdk.jpackage.test.WindowsHelper.killAppLauncherProcess; /* @test * @bug 8340311 @@ -92,16 +93,18 @@ void apply(JPackageCommand cmd, CfgFile origCfgFile) throws InterruptedException // Save updated main launcher .cfg file cfgFile.save(cmd.appLauncherCfgPath(null)); - // Launch the app in a separate thread - new Thread(() -> { - HelloApp.executeLauncher(cmd); - }).start(); + try ( // Launch the app in a separate thread + ExecutorService exec = Executors.newSingleThreadExecutor()) { + exec.execute(() -> { + HelloApp.executeLauncher(cmd); + }); - // Wait a bit to let the app start - Thread.sleep(Duration.ofSeconds(10)); + // Wait a bit to let the app start + Thread.sleep(Duration.ofSeconds(10)); - // Find the main app launcher process and kill it - killAppLauncherProcess(cmd, null, expectedNoRestarted ? 1 : 2); + // Find the main app launcher process and kill it + killAppLauncherProcess(cmd, null, expectedNoRestarted ? 1 : 2); + } } } diff --git a/test/jdk/tools/launcher/ChangeDataModel.java b/test/jdk/tools/launcher/ChangeDataModel.java index 1494504543574..e6bc281ad624d 100644 --- a/test/jdk/tools/launcher/ChangeDataModel.java +++ b/test/jdk/tools/launcher/ChangeDataModel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2017, 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,6 +27,7 @@ * @compile -XDignore.symbol.file ChangeDataModel.java * @run main ChangeDataModel * @summary Verify -d32, -d64 and -J prefixed data-model options are rejected on all platforms + * @author Joseph D. Darcy, ksrini */ import java.util.Arrays; diff --git a/test/jdk/tools/launcher/I18NTest.java b/test/jdk/tools/launcher/I18NTest.java index 83d90f56327f4..aa1ce24e798c8 100644 --- a/test/jdk/tools/launcher/I18NTest.java +++ b/test/jdk/tools/launcher/I18NTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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,6 +27,7 @@ * @compile -XDignore.symbol.file I18NTest.java * @run main I18NTest * @summary Test to see if class files with non-ASCII characters can be run + * @author Joseph D. Darcy, Kumar Srinivasan */ diff --git a/test/jdk/tools/launcher/UnresolvedExceptions.java b/test/jdk/tools/launcher/UnresolvedExceptions.java index 6faa306c34c08..ce14f405aeddc 100644 --- a/test/jdk/tools/launcher/UnresolvedExceptions.java +++ b/test/jdk/tools/launcher/UnresolvedExceptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ * @compile -XDignore.symbol.file UnresolvedExceptions.java * @run main UnresolvedExceptions * @summary Verifying jvm won't segv if exception not available + * @author Joseph D. Darcy, ksrini */ import java.io.File; diff --git a/test/jtreg-ext/requires/VMProps.java b/test/jtreg-ext/requires/VMProps.java index 3c06c97b37a0e..29057f24d3b60 100644 --- a/test/jtreg-ext/requires/VMProps.java +++ b/test/jtreg-ext/requires/VMProps.java @@ -149,7 +149,6 @@ public Map call() { vmGC(map); // vm.gc.X = true/false vmGCforCDS(map); // may set vm.gc vmOptFinalFlags(map); - vmOptFinalIntxFlags(map); dump(map.map); log("Leaving call()"); @@ -390,26 +389,6 @@ protected void vmOptFinalFlags(SafeMap map) { vmOptFinalFlag(map, "UseVectorizedMismatchIntrinsic"); } - /** - * Selected final flag of type intx. - * - * @param map - property-value pairs - * @param flagName - flag name - */ - private void vmOptFinalIntxFlag(SafeMap map, String flagName) { - map.put("vm.opt.final." + flagName, - () -> String.valueOf(WB.getIntxVMFlag(flagName))); - } - - /** - * Selected sets of final flags of type intx. - * - * @param map - property-value pairs - */ - protected void vmOptFinalIntxFlags(SafeMap map) { - vmOptFinalIntxFlag(map, "MaxVectorSize"); - } - /** * @return "true" if VM has a serviceability agent. */ diff --git a/test/langtools/jdk/javadoc/tool/api/basic/APITest.java b/test/langtools/jdk/javadoc/tool/api/basic/APITest.java index 71908f34e9964..e4e3c6baa87b2 100644 --- a/test/langtools/jdk/javadoc/tool/api/basic/APITest.java +++ b/test/langtools/jdk/javadoc/tool/api/basic/APITest.java @@ -215,7 +215,6 @@ protected void error(String msg) { "resource-files/stylesheet.css", "resource-files/sun.svg", "resource-files/x.svg", - "resource-files/sort-a-z.svg", "resource-files/fonts/dejavu.css", "resource-files/fonts/DejaVuLGCSans-Bold.woff", "resource-files/fonts/DejaVuLGCSans-Bold.woff2", @@ -266,3 +265,4 @@ protected void error(String msg) { && !s.equals("system-properties.html")) .collect(Collectors.toSet()); } + diff --git a/test/langtools/jdk/jshell/JdiBadOptionListenExecutionControlTest.java b/test/langtools/jdk/jshell/JdiBadOptionListenExecutionControlTest.java index 130913df8d43f..422c6c18b7565 100644 --- a/test/langtools/jdk/jshell/JdiBadOptionListenExecutionControlTest.java +++ b/test/langtools/jdk/jshell/JdiBadOptionListenExecutionControlTest.java @@ -47,7 +47,7 @@ public void badOptionListenTest() { // turn on logging of launch failures Logger.getLogger("jdk.jshell.execution").setLevel(Level.ALL); JShell.builder() - .executionEngine(Presets.TEST_JDI_EXECUTION) + .executionEngine("jdi") .remoteVMOptions("-BadBadOption") .build(); } catch (IllegalStateException ex) { diff --git a/test/langtools/jdk/jshell/JdiListeningExecutionControlTest.java b/test/langtools/jdk/jshell/JdiListeningExecutionControlTest.java index a941845ba497f..3cc2a9785a3c5 100644 --- a/test/langtools/jdk/jshell/JdiListeningExecutionControlTest.java +++ b/test/langtools/jdk/jshell/JdiListeningExecutionControlTest.java @@ -39,6 +39,6 @@ public class JdiListeningExecutionControlTest extends ExecutionControlTestBase { @BeforeEach @Override public void setUp() { - setUp(builder -> builder.executionEngine(Presets.TEST_JDI_EXECUTION)); + setUp(builder -> builder.executionEngine("jdi")); } } diff --git a/test/langtools/jdk/jshell/Presets.java b/test/langtools/jdk/jshell/Presets.java index afe193ee5c3ae..b9a93c967dc71 100644 --- a/test/langtools/jdk/jshell/Presets.java +++ b/test/langtools/jdk/jshell/Presets.java @@ -25,23 +25,16 @@ import java.util.*; public class Presets { - private static final int TEST_TIMEOUT = 20_000; - public static final String TEST_DEFAULT_EXECUTION; public static final String TEST_STANDARD_EXECUTION; - public static final String TEST_JDI_EXECUTION; static { String loopback = InetAddress.getLoopbackAddress().getHostAddress(); TEST_DEFAULT_EXECUTION = "failover:0(jdi:hostname(" + loopback + "))," + - "1(jdi:launch(true))," + - "2(jdi:timeout(" + TEST_TIMEOUT + "))," + - "3(local)"; + "1(jdi:launch(true)), 2(jdi), 3(local)"; TEST_STANDARD_EXECUTION = "failover:0(jdi:hostname(" + loopback + "))," + - "1(jdi:launch(true))," + - "2(jdi:timeout(" + TEST_TIMEOUT + "))"; - TEST_JDI_EXECUTION = "jdi:timeout(" + TEST_TIMEOUT + ")"; + "1(jdi:launch(true)), 2(jdi)"; } public static String[] addExecutionIfMissing(String[] args) { diff --git a/test/lib/jdk/test/lib/containers/cgroup/MetricsTesterCgroupV2.java b/test/lib/jdk/test/lib/containers/cgroup/MetricsTesterCgroupV2.java index 2a756102dede8..a3723e2eda274 100644 --- a/test/lib/jdk/test/lib/containers/cgroup/MetricsTesterCgroupV2.java +++ b/test/lib/jdk/test/lib/containers/cgroup/MetricsTesterCgroupV2.java @@ -1,6 +1,5 @@ /* * Copyright (c) 2020, Red Hat Inc. - * 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 @@ -448,13 +447,13 @@ private void testIOStat() { Metrics metrics = Metrics.systemMetrics(); long oldVal = metrics.getBlkIOServiceCount(); long newVal = getIoStatAccumulate(new String[] { "rios", "wios" }); - if (newVal < oldVal) { + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { fail("io.stat->rios/wios: ", oldVal, newVal); } oldVal = metrics.getBlkIOServiced(); newVal = getIoStatAccumulate(new String[] { "rbytes", "wbytes" }); - if (newVal < oldVal) { + if (!CgroupMetricsTester.compareWithErrorMargin(oldVal, newVal)) { fail("io.stat->rbytes/wbytes: ", oldVal, newVal); } } diff --git a/test/lib/jdk/test/lib/security/CertificateBuilder.java b/test/lib/jdk/test/lib/security/CertificateBuilder.java index d35a21e7ab5ee..e5044d46b0f9b 100644 --- a/test/lib/jdk/test/lib/security/CertificateBuilder.java +++ b/test/lib/jdk/test/lib/security/CertificateBuilder.java @@ -53,7 +53,6 @@ import sun.security.x509.SubjectAlternativeNameExtension; import sun.security.x509.URIName; import sun.security.x509.KeyIdentifier; -import sun.security.x509.X500Name; /** @@ -91,7 +90,7 @@ public class CertificateBuilder { private final CertificateFactory factory; - private X500Name subjectName = null; + private X500Principal subjectName = null; private BigInteger serialNumber = null; private PublicKey publicKey = null; private Date notBefore = null; @@ -200,7 +199,7 @@ public CertificateBuilder() throws CertificateException { * on this certificate. */ public CertificateBuilder setSubjectName(X500Principal name) { - subjectName = X500Name.asX500Name(name); + subjectName = name; return this; } @@ -210,23 +209,7 @@ public CertificateBuilder setSubjectName(X500Principal name) { * @param name The subject name in RFC 2253 format */ public CertificateBuilder setSubjectName(String name) { - try { - subjectName = new X500Name(name); - } catch (IOException ioe) { - throw new IllegalArgumentException(ioe); - } - return this; - } - - /** - * Set the subject name for the certificate. This method is useful when - * you need more control over the contents of the subject name. - * - * @param name an {@code X500Name} to be used as the subject name - * on this certificate - */ - public CertificateBuilder setSubjectName(X500Name name) { - subjectName = name; + subjectName = new X500Principal(name); return this; } diff --git a/test/micro/org/openjdk/bench/java/lang/Doubles.java b/test/micro/org/openjdk/bench/java/lang/FloatingDecimal.java similarity index 89% rename from test/micro/org/openjdk/bench/java/lang/Doubles.java rename to test/micro/org/openjdk/bench/java/lang/FloatingDecimal.java index 50c295900af8a..b8d29aabc8440 100644 --- a/test/micro/org/openjdk/bench/java/lang/Doubles.java +++ b/test/micro/org/openjdk/bench/java/lang/FloatingDecimal.java @@ -1,6 +1,5 @@ /* - * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2025, Alibaba Group Holding Limited. All Rights Reserved. + * Copyright (c) 2014, 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 @@ -48,7 +47,7 @@ @Warmup(iterations = 10, time = 1) @Measurement(iterations = 5, time = 2) @Fork(3) -public class Doubles { +public class FloatingDecimal { private double[] randomArray, twoDecimalsArray, integerArray; private static final int TESTSIZE = 1000; @@ -66,14 +65,6 @@ public void setup() { } } - @Benchmark - @OperationsPerInvocation(TESTSIZE) - public void toHexString(Blackhole bh) { - for (double d : randomArray) { - bh.consume(Double.toHexString(d)); - } - } - /** Tests Double.toString on double values generated from Random.nextDouble() */ @Benchmark @OperationsPerInvocation(TESTSIZE) diff --git a/test/micro/org/openjdk/bench/java/lang/runtime/RecordMethodsBenchmark.java b/test/micro/org/openjdk/bench/java/lang/runtime/RecordMethodsBenchmark.java deleted file mode 100644 index 91d26601383a0..0000000000000 --- a/test/micro/org/openjdk/bench/java/lang/runtime/RecordMethodsBenchmark.java +++ /dev/null @@ -1,171 +0,0 @@ -/* - * 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 org.openjdk.bench.java.lang.runtime; - -import java.util.Objects; -import java.util.concurrent.TimeUnit; - -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.BenchmarkMode; -import org.openjdk.jmh.annotations.Fork; -import org.openjdk.jmh.annotations.Measurement; -import org.openjdk.jmh.annotations.Mode; -import org.openjdk.jmh.annotations.OutputTimeUnit; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.Warmup; - -/// Tests the generated equals and hashCode for records. -/// There are 4 types of methods: -/// - distinct: distinct sites for type profiling -/// - polluted: megamorphic site that blocks type profiling -/// - generated: actual body generated by ObjectMethods::bootstrap -/// - specialized: generated body for non-extensible types -/// The result of generated compared to the other distinct/polluted shows -/// whether the generated code could perform type profiling. -/// Specialized is the result of distinct without trap, should be even faster. -@Fork(3) -@Warmup(iterations = 10, time = 1) -@Measurement(iterations = 5, time = 2) -@OutputTimeUnit(TimeUnit.MICROSECONDS) -@BenchmarkMode(Mode.Throughput) -public class RecordMethodsBenchmark { - - record One(int a) {} - - @State(Scope.Thread) - public static class BenchmarkState { - Key k1 = new Key(new One(1), "a"); - Key k2 = new Key(new One(1), new String("a")); - SpecializedKey sk1 = new SpecializedKey(new One(1), "a"); - SpecializedKey sk2 = new SpecializedKey(new One(1), new String("a")); - } - - @Benchmark - public int hashCodeDistinct(BenchmarkState state) { - return state.k1.hashCodeDistinct(); - } - - @Benchmark - public int hashCodePolluted(BenchmarkState state) { - return state.k1.hashCodePolluted(); - } - - @Benchmark - public int hashCodeGenerated(BenchmarkState state) { - return state.k1.hashCode(); - } - - @Benchmark - public int hashCodeSpecial(BenchmarkState state) { - return state.sk1.hashCode(); - } - - @Benchmark - public boolean equalsDistinct(BenchmarkState state) { - return state.k1.equalsDistinct(state.k2); - } - - @Benchmark - public boolean equalsPolluted(BenchmarkState state) { - return state.k1.equalsPolluted(state.k2); - } - - @Benchmark - public boolean equalsGenerated(BenchmarkState state) { - return state.k1.equals(state.k2); - } - - @Benchmark - public boolean equalsSpecial(BenchmarkState state) { - return state.sk1.equals(state.sk2); - } - - /// A key object. - /// - /// Having both field as Object pollutes Object.equals for record object - /// method MH tree. We must verify the leaf Object.equals calls don't - /// share the same profile in generated code. - record Key(Object key1, Object key2) { - /// A hashCode method which has distinct hashCode invocations - /// in bytecode for each field for type profiling. - public int hashCodeDistinct() { - final int prime = 31; - int result = 1; - result = prime * result + ((key1 == null) ? 0 : key1.hashCode()); - result = prime * result + ((key2 == null) ? 0 : key2.hashCode()); - return result; - } - - /// A hashCode method which uses a megamorphic polluted - /// Object.hashCode virtual invocation in Objects.hashCode. - public int hashCodePolluted() { - final int prime = 31; - int result = 1; - result = prime * result + Objects.hashCode(key1); - result = prime * result + Objects.hashCode(key2); - return result; - } - - /// An equals method which has distinct equals invocations - /// in bytecode for each field for type profiling. - public boolean equalsDistinct(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Key other = (Key) obj; - if (key1 == null) { - if (other.key1 != null) - return false; - } - else if (!key1.equals(other.key1)) - return false; - if (key2 == null) { - if (other.key2 != null) - return false; - } - else if (!key2.equals(other.key2)) - return false; - return true; - } - - /// An equals method which uses a megamorphic polluted - /// Object.equals virtual invocation in Objects.equals. - public boolean equalsPolluted(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Key other = (Key) obj; - return Objects.equals(key1, other.key1) && Objects.equals(key2, other.key2); - } - } - - record SpecializedKey(One key1, String key2) {} -} diff --git a/test/micro/org/openjdk/bench/javax/crypto/AESDecrypt.java b/test/micro/org/openjdk/bench/javax/crypto/AESDecrypt.java deleted file mode 100644 index 0514a6d25f3c2..0000000000000 --- a/test/micro/org/openjdk/bench/javax/crypto/AESDecrypt.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * 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 org.openjdk.bench.javax.crypto; - -import org.openjdk.jmh.annotations.Fork; -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.OutputTimeUnit; -import org.openjdk.jmh.annotations.Param; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.Setup; -import org.openjdk.jmh.annotations.State; - -import javax.crypto.Cipher; -import javax.crypto.spec.IvParameterSpec; -import javax.crypto.spec.SecretKeySpec; -import java.util.Random; -import java.util.concurrent.TimeUnit; - -@OutputTimeUnit(TimeUnit.SECONDS) -@State(Scope.Thread) -public class AESDecrypt { - - @Param("10000000") - private int count; - - private Cipher cipher; - private byte[] src; - private byte[] ct; - - @Setup - public void setup() throws Exception { - SecretKeySpec keySpec = new SecretKeySpec(new byte[]{-80, -103, -1, 68, -29, -94, 61, -52, 93, -59, -128, 105, 110, 88, 44, 105}, "AES"); - IvParameterSpec iv = new IvParameterSpec(new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}); - - cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); - cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv); - - src = new byte[count]; - new Random(1).nextBytes(src); - - ct = cipher.doFinal(src); - - cipher.init(Cipher.DECRYPT_MODE, keySpec, iv); - } - - @Benchmark - @Fork(jvmArgs = {"-XX:+UnlockDiagnosticVMOptions", "-XX:-UseAES", "-XX:-UseAESIntrinsics"}) - public byte[] testBaseline() throws Exception { - return cipher.doFinal(ct); - } - - @Benchmark - @Fork(jvmArgs = {"-XX:+UnlockDiagnosticVMOptions", "-XX:+UseAES", "-XX:-UseAESIntrinsics"}) - public byte[] testUseAes() throws Exception { - return cipher.doFinal(ct); - } - - @Benchmark - @Fork(jvmArgs = {"-XX:+UnlockDiagnosticVMOptions", "-XX:+UseAES", "-XX:+UseAESIntrinsics"}) - public byte[] testUseAesIntrinsics() throws Exception { - return cipher.doFinal(ct); - } - -}