From d7bf41b302ace6ce3aa309c3be1aa71afe4bf2b3 Mon Sep 17 00:00:00 2001 From: AlmaLinux RelEng Bot Date: Wed, 22 Jul 2026 19:08:48 -0400 Subject: [PATCH] import UBI java-25-openjdk-25.0.4.0.7-1.1.el10_2 --- .gitignore | 2 +- NEWS | 347 ++++++++ TestTranslations.java | 54 +- java-25-openjdk-portable.specfile | 399 +++++---- java-25-openjdk.spec | 351 ++++---- jdk8347901-c2_unused_leaf_removal.patch | 772 ++++++++++++++++++ jdk8375294-handle-EOPNOTSUPP-in-copying.patch | 63 -- ...8713-c2_missing_pow_constant_folding.patch | 626 ++++++++++++++ sources | 2 +- 9 files changed, 2154 insertions(+), 462 deletions(-) create mode 100644 jdk8347901-c2_unused_leaf_removal.patch delete mode 100644 jdk8375294-handle-EOPNOTSUPP-in-copying.patch create mode 100644 jdk8378713-c2_missing_pow_constant_folding.patch diff --git a/.gitignore b/.gitignore index 09ad09e..2bac8a5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ nssadapter-0.1.1.tar.xz -openjdk-25.0.3+9.tar.xz +openjdk-25.0.4+7.tar.xz tapsets-icedtea-6.0.0pre00-c848b93a8598.tar.xz diff --git a/NEWS b/NEWS index 3b1de67..66eba57 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,353 @@ Key: JDK-X - https://bugs.openjdk.java.net/browse/JDK-X CVE-XXXX-YYYY: https://cve.mitre.org/cgi-bin/cvename.cgi?name=XXXX-YYYY +New in release OpenJDK 25.0.4 (2026-07-21): +=========================================== +Live versions of these release notes can be found at: + * https://bit.ly/openjdk2504 + +* CVEs +* Changes + - JDK-7184899: Test sun/java2d/X11SurfaceData/SharedMemoryPixmapsTest/SharedMemoryPixmapsTest.sh fail + - JDK-8015444: java/awt/Focus/KeyStrokeTest.java sometimes fails + - JDK-8064922: [macos] Test javax/swing/JTabbedPane/4624207/bug4624207.java fails + - JDK-8068293: [TEST_BUG] Test closed/com/sun/java/swing/plaf/motif/InternalFrame/4150591/bug4150591.java fails with GTKLookAndFeel + - JDK-8068310: [TEST_BUG] Test javax/swing/JColorChooser/Test4234761.java fails with GTKL&F + - JDK-8144124: [macosx] The tabs can't be aligned when we pressing the key of 'R','B','L','C' or 'T'. + - JDK-8203004: UnixMultiResolutionSplashTest.java fails on Ubuntu16.04 + - JDK-8213530: Test java/awt/Modal/ToFront/DialogToFrontModeless1Test.java fails on Linux + - JDK-8221451: PIT: sun/java2d/X11SurfaceData/SharedMemoryPixmapsTest/SharedMemoryPixmapsTest.sh fails + - JDK-8225787: java/awt/Window/GetScreenLocation/GetScreenLocationTest.java fails on Ubuntu + - JDK-8241066: Shenandoah: fix or cleanup SH::do_full_collection + - JDK-8261743: Shenandoah: enable String deduplication with compact heuristics + - JDK-8264851: Shenandoah: Rework control loop mechanics to use timed waits + - JDK-8278102: containers/docker/TestJcmd.java failed with "RuntimeException: Could not find specified process" + - JDK-8279196: Test: jdk/jfr/event/gc/stacktrace/TestG1OldAllocationPendingStackTrace.java timed out + - JDK-8297191: [macos] Printing a page range with starting page > 1 results in missing pages + - JDK-8298823: [macos] java/awt/Mouse/EnterExitEvents/DragWindowTest.java continues to fail with "No MouseReleased event on label!" + - JDK-8319326: GC: Make TestParallelRefProc use createTestJavaProcessBuilder + - JDK-8319540: GC: Make TestSelectDefaultGC use createTestJavaProcessBuilder + - JDK-8321303: Intermittent open/test/jdk/java/awt/KeyboardFocusmanager/ConsumeNextMnemonicKeyTypedTest/ConsumeNextMnemonicKeyTypedTest.java failure on Linux + - JDK-8321687: Test vmTestbase/nsk/jvmti/scenarios/contention/TC03/tc03t002/TestDescription.java failed: JVMTI_ERROR_THREAD_NOT_ALIVE + - JDK-8323792: ThreadSnapshot::initialize can cause assert in Thread::check_for_dangling_thread_pointer (possibility of dangling Thread pointer) + - JDK-8325482: Test that distinct seeds produce distinct traces for compiler stress flags + - JDK-8335355: Shenandoah: Fix race condition in gc/shenandoah/mxbeans/TestPauseNotifications.java + - JDK-8339526: C2: store incorrectly removed for clone() transformed to series of loads/stores + - JDK-8340182: Java HttpClient does not follow default retry limit of 3 retries + - JDK-8341735: Rewrite the build/AbsPathsInImage.java test to not load the entire file at once + - JDK-8344345: test/hotspot/gtest/x86/x86-asmtest.py has trailing whitespaces + - JDK-8345631: TestRegionSamplingLogging.java#generational-rotation intermittent fails + - JDK-8347167: Reduce allocation in com.sun.net.httpserver.Headers::normalize + - JDK-8347938: Add Support for the Latest ML-KEM and ML-DSA Private Key Encodings + - JDK-8351010: Test java/io/File/GetXSpace.java failed: / usable space 56380809216 > free space 14912244940 + - JDK-8352914: Shenandoah: Change definition of ShenandoahSharedValue to int32_t to leverage platform atomics + - JDK-8353115: GenShen: mixed evacuation candidate regions need accurate live_data + - JDK-8354650: [PPC64] Try to reduce register definitions + - JDK-8355339: Test java/io/File/GetCanonicalPath.java failed: The specified network name is no longer available + - JDK-8357086: os::xxx functions returning memory size should return size_t + - JDK-8358600: Template-Framework Library: Template for TestFramework test class + - JDK-8358772: Template-Framework Library: Primitive Types + - JDK-8359083: Test jdkCheckHtml.java should report SkippedException rather than report fails when miss tidy + - JDK-8359223: HttpClient: Remove leftovers from the SecurityManager cleanup + - JDK-8359412: Template-Framework Library: Operations and Expressions + - JDK-8359433: The final modifier on Windows L&F internal UI classes prevents extending them in apps + - JDK-8361339: Test gc/shenandoah/TestLargeObjectAlignment.java#generational fails on macOS aarch64 with OOM: Java heap space + - JDK-8361606: ConsumeNextMnemonicKeyTypedTest.java fails on Windows: character typed with VK_A: a + - JDK-8361699: C2: assert(can_reduce_phi(n->as_Phi())) failed: Sanity: previous reducible Phi is no longer reducible before SUT + - JDK-8361726: Shenandoah: More detailed evacuation instrumentation + - JDK-8362428: Update IANA Language Subtag Registry to Version 2025-08-25 + - JDK-8363943: ARM32: Represent Registers as values + - JDK-8363949: Incorrect jtreg header in MonitorWithDeadObjectTest.java + - JDK-8363986: Heap region in CDS archive is not at deterministic address + - JDK-8364315: Remove unused xml files from test/jaxp/javax/xml/jaxp/functional/javax/xml/transform/xmlfiles + - JDK-8364657: Crash for SecureRandom.generateSeed(0) on Windows x86-64 + - JDK-8364927: Add @requires annotation to TestReclaimStringsLeaksMemory.java + - JDK-8365057: Add support for java.util.concurrent lock information to Thread.dump_to_file + - JDK-8365379: SU3.applyInsets may produce wrong results + - JDK-8365423: [macos26] java/awt/MenuBar/8007006/bug8007006.java fails on macOS 26 + - JDK-8365424: [macos26] java/awt/Frame/DisposeTest.java fails on macOS 26 + - JDK-8365623: test/jdk/sun/security/pkcs11/tls/ tests skipped without skip exception + - JDK-8365625: Can't change accelerator colors in Windows L&F + - JDK-8365792: GenShen: assertion "Generations aren't reconciled" + - JDK-8366692: Several gc/shenandoah tests timed out + - JDK-8366695: Test sun/jvmstat/monitor/MonitoredVm/MonitorVmStartTerminate.java timed out + - JDK-8366852: java/awt/Choice/ChoiceMouseWheelTest/ChoiceMouseWheelTest.java test is failing + - JDK-8367096: jdk/open/test/jdk/sun/security/pkcs11/ rsa, ec, config, secmod and sslecc tests are skipping but showing as pass + - JDK-8367450: Shenandoah: Log the composition of the collection set + - JDK-8367451: GenShen: Remove the option to compute age census during evacuation + - JDK-8367473: Shenandoah: Make the detailed evacuation metrics a runtime diagnostic option + - JDK-8367485: os::physical_memory is broken in 32-bit JVMs when running on 64-bit OSes + - JDK-8367531: Template Framework: use scopes and tokens instead of misbehaving immediate-return-queries + - JDK-8367646: [GenShen] Control thread may overwrite gc cancellation cause set by mutator + - JDK-8367708: GenShen: Reduce total evacuation burden + - JDK-8367709: GenShen: Dirty cards for objects that get promoted by safepoint that intervenes between allocation and stores + - JDK-8367722: [GenShen] ShenandoahEvacuationStats is always empty + - JDK-8367949: JFR: MethodTrace double-counts methods that catch their own exceptions + - JDK-8368001: java/text/Format/NumberFormat/NumberRoundTrip.java timed out + - JDK-8368015: Shenandoah: fix error in computation of average allocation rate + - JDK-8368041: Enhance TLS certificate handling + - JDK-8368159: Significant performance overhead when started with jdwp agent and unattached debugger + - JDK-8368181: ProblemList java/awt/Dialog/ModalExcludedTest/ModalExcludedTest.java + - JDK-8368307: Shenandoah: get_next_bit_impl should special case weak and strong mark bits + - JDK-8368499: GenShen: Do not collect age census during evac when adaptive tenuring is disabled + - JDK-8368501: Shenandoah: GC progress evaluation does not use generation + - JDK-8368524: Tests are skipped and shown as passed in test/jdk/sun/security/pkcs11/Cipher/KeyWrap + - JDK-8368681: Shenandoah: Add documentation comments for ShenandoahAllocationRate + - JDK-8369128: ProblemList jdk/jfr/event/profiling/TestCPUTimeSampleQueueAutoSizes.java in Xcomp configs + - JDK-8369132: Disable vmTestbase/gc/vector/CircularListLow and LinearListLow with SerialGC + - JDK-8369133: Disable gc/g1/TestShrinkAuxiliaryDataRunner.java with UseLargePages option + - JDK-8369251: Opensource few tests + - JDK-8369561: sun/java2d/OpenGL/DrawBitmaskImage.java#id0: Incorrect color for first pixel (actual=ff000000) + - JDK-8369683: Exclude runtime/Monitor/MonitorWithDeadObjectTest.java#DumpThreadsBeforeDetach on Alpine Linux debug + - JDK-8369736: Add management interface for AOT cache creation + - JDK-8369817: [TESTBUG] EmptyPath::toString is ignored + - JDK-8369912: [TESTBUG] testlibrary_tests/template_framework/examples/TestExpressions.java fails with ArithmeticException: / by zero - forgot to respect Expression.info + - JDK-8369950: TLS connection to IPv6 address fails with BCJSSE due to IllegalArgumentException + - JDK-8370370: Add still more cases to WorstCaseTests + - JDK-8370489: Some compiler tests miss the @key randomness + - JDK-8370502: C2: segfault while adding node to IGVN worklist + - JDK-8370521: GenShen: Various code cleanup related to promotion + - JDK-8370939: C2: SIGSEGV in SafePointNode::verify_input when processing MH call from Compile::process_late_inline_calls_no_inline() + - JDK-8371284: GenShen: Avoid unnecessary card marking + - JDK-8371381: [Shenandoah] Setting ergo flags should use FLAG_SET_ERGO + - JDK-8371503: RETAIN_IMAGE_AFTER_TEST do not work for some tests + - JDK-8371792: Refactor barrier loop tests out of TestIfMinMax + - JDK-8371893: [macOS] use dead_strip linker option to reduce binary size + - JDK-8372272: Hotspot shared lib loading - add load attempts to Events::log + - JDK-8372351: Add 2 WISeKey roots + - JDK-8372380: Make hs_err reporting more robust for unattached threads + - JDK-8372513: Shenandoah: ShenandoahMaxRegionSize can produce an unaligned heap alignment + - JDK-8372851: Modify java/io/File/GetXSpace.java to print path on failure of native call + - JDK-8372861: Genshen: Override parallel_region_stride of ShenandoahResetBitmapClosure to a reasonable value for better parallelism + - JDK-8373039: Remove Incorrect Asserts in shenandoahScanRemembered + - JDK-8373120: Virtual thread stuck in BLOCKED state + - JDK-8373239: Test java/awt/print/PrinterJob/PageRanges.java fails with incorrect selection of printed pages + - JDK-8373275: Improve DTLS handshaking + - JDK-8373515: Migrate "test/jdk/java/net/httpclient/" to null-safe "SimpleSSLContext" methods + - JDK-8373579: Problem list compiler/runtime/Test7196199.java + - JDK-8373650: Test "javax/swing/JMenuItem/6458123/ManualBug6458123.java" fails because the check icons are not aligned properly as expected + - JDK-8373676: Test javax/net/ssl/HttpsURLConnection/SubjectAltNameIP.java fails on a machine without IPV6 + - JDK-8373690: Unexpected Keystore message using jdk.crypto.disabledAlgorithms + - JDK-8373714: Shenandoah: Register heuristic penalties following a degenerated GC + - JDK-8373718: jdk/internal/misc/VM/RuntimeArguments.java test fails in Virtual threads mode + - JDK-8373796: Refactor java/net/httpclient/ThrowingPublishers*.java tests to use JUnit5 + - JDK-8373847: Test javax/swing/JMenuItem/MenuItemTest/bug6197830.java failed because The test case automatically fails when clicking any items in the “Nothing” menu in all four windows (Left-to-right)-Menu Item Test and (Right-to-left)-Menu Item Test + - JDK-8373866: Refactor java/net/httpclient/ThrowingSubscribers*.java tests to use JUnit5 + - JDK-8373893: Refactor networking http server tests to use JUnit + - JDK-8373913: Refactor serialization tests to use JUnit + - JDK-8373928: 4 Dangling pointer defect groups in java.c + - JDK-8374001: sun/security/ skip without Exceptions + - JDK-8374058: Enhance JPEG handling + - JDK-8374168: Resolve disabled warnings in JDWP agent + - JDK-8374304: MultiResolutionSplashTest.java fails in CI: "Image with wrong resolution is used for splash screen!" + - JDK-8374322: TestMemoryWithSubgroups.java fails Permission denied + - JDK-8374343: Fix SIGSEGV when lib/modules is unreadable + - JDK-8374449: Shenandoah: Leaf locks used by Shenandoah need lower ranks + - JDK-8374506: Incorrect positioning of arrow icon in parent JMenu in Windows L&F + - JDK-8374712: AOTMappedHeapWriter::relocate_field_in_buffer should use CompressedOops::narrow_oop_cast + - JDK-8374727: Audio configuration Platform class - use nio for getting endianness of the underlying platform + - JDK-8374744: Enable dumping of APX EGPRs (R16–R31) in JVM fatal error logs + - JDK-8374769: PPC: MASM::pop_cont_fastpath() should reset _cont_fastpath if SP == _cont_fastpath + - JDK-8374888: Implement internal test cache to help UserIterCount test performance + - JDK-8374998: Failing os::write - remove bad file + - JDK-8375065: Update LCMS to 2.18 + - JDK-8375177: Gtest os_linux.decoder_get_source_info_valid_vm fails with -ffunction-sections + - JDK-8375294: (fs) Files.copy can fail with EOPNOTSUPP when copy_file_range not supported + - JDK-8376031: HttpsURLConnection.getServerCertificates() throws "java.lang.IllegalStateException: connection not yet open" for the HEAD method + - JDK-8376104: C2 crashes in PhiNode::Ideal(PhaseGVN*, bool) accessing NULL pointer + - JDK-8376151: Test javax/swing/JFileChooser/4966171/bug4966171.java is failing with OOME + - JDK-8376152: Test javax/sound/sampled/Clip/bug5070081.java timed out then completed + - JDK-8376185: NoSuchFieldError thrown after a record with type annotation retransformed + - JDK-8376233: Clean up code in Desktop native peer + - JDK-8376287: Crashes when using -XX:ObjArrayMarkingStride=0 + - JDK-8376402: Dependencies::print_statistics() and AbstractClassHierarchyWalker::print_statistics() are not called from PRODUCT code + - JDK-8376684: Compile OpenJDK in headless mode without required X11 libraries + - JDK-8376956: Add JVMTI phase entering/setting to hserr event log + - JDK-8376969: Shenandoah: GC state getters should be inlineable + - JDK-8376970: Shenandoah: Verifier should do basic verification before touching oops + - JDK-8377158: Enhance XBM image support + - JDK-8377167: javax/imageio/ReadAbortTest.java throw NPE when x11 unavailable + - JDK-8377498: Improve HttpServer handling + - JDK-8377512: AOT cache creation fails with invalid native pointer + - JDK-8377602: Create automated test for PageRange + - JDK-8377727: Ghost caret and focus appear in non‑editable text fields + - JDK-8377833: Enhance Jar file processing + - JDK-8377907: (process) Race in ProcessBuilder can cause JVM hangs + - JDK-8377910: Minor cleanup of java/io/FileDescriptor/Sharing.java + - JDK-8377932: AOT cache is not rejected when JAR file has changed + - JDK-8377944: LowMemoryTest2.java#id1 intermittent fails OOME: Metaspace + - JDK-8377949: TestZRelocationSetEvent.java intermittent fails OOME + - JDK-8378083: Mark shenandoah/generational/TestOldGrowthTriggers.java as flagless + - JDK-8378201: [OGL] glXMakeContextCurrent() drops the buffers of the unbound drawable + - JDK-8378417: Printing All pages results in NPE for 1.1 PrintJob + - JDK-8378561: Mark gc/shenandoah/compiler/TestLinkToNativeRBP.java as /native + - JDK-8378687: Improve delegation of HttpURLConnection + - JDK-8378727: [macOS] Missing dispatch_release for semaphores in CDesktopPeer + - JDK-8378746: ZGC: jdk/jfr/event/gc/detailed/TestZRelocationSetGroupEvent.java intermittent OOME + - JDK-8378764: fileStream::fileSize() fails for >2GB files on Windows + - JDK-8378774: Bump update version for OpenJDK: jdk-25.0.4 + - JDK-8378810: Enable missing FFM test via jtreg requires for RISC-V + - JDK-8378836: Enable linktime-gc by default on Linux ppc64le + - JDK-8378878: Refactor java/nio/channels/AsynchronousSocketChannel test to use JUnit + - JDK-8378888: jdk/incubator/vector/Float16OperationsBenchmark.java uses wrong package name + - JDK-8379021: Shenandoah: Speedup ShenandoahSimpleBitMapTest + - JDK-8379202: Support linktime-gc on Linux with clang + - JDK-8379416: AIX build fails if system (not GNU) date tool is in PATH + - JDK-8379425: Windows and macOS should not allow unsupported headless-only build + - JDK-8379457: Test EATests.java#id0 ERROR: monitor list errors: error_cnt=1 + - JDK-8379464: Enable missing stack walking test via jtreg requires for RISC-V + - JDK-8379499: [AIX] headless-only build of libjawt.so fails + - JDK-8379515: draft-ietf-lamps-kyber-certificates is now RFC 9935 + - JDK-8380011: Path-to-gcroots search should not trigger stack overflows + - JDK-8380041: PPC: remove POWER6 remnants + - JDK-8380222: Refactor test/jdk/java/lang/Character TestNG tests to JUnit + - JDK-8380316: Test runtime/os/AvailableProcessors.java fails Invalid argument + - JDK-8380409: JVM crashes when -XX:AOTMode=create uses app.aotconf generated with JVMTI agent + - JDK-8380428: ProblemList containers/docker/TestJcmdWithSideCar.java on linux-all + - JDK-8380431: Shenandoah: Concurrent modification of stack-chunk objects during evacuation + - JDK-8380474: Crash SEGV in ThreadIdTable::lazy_initialize after JDK-8323792 + - JDK-8380565: PPC64: deoptimization stub should save vector registers + - JDK-8380663: Update jcmd man page to include AOT.end_recording diagnostic command + - JDK-8380672: Improve certification checking + - JDK-8380846: GenShen: Remove the experimental option to disable adaptive tenuring + - JDK-8380947: Add pull request template + - JDK-8381039: Enhance AWT ImagingLib + - JDK-8381049: Enhance Jar handling + - JDK-8381205: GHA: Upgrade Node.js 20 to 24 + - JDK-8381315: compiler/vectorapi/TestVectorReallocation.java fails with -XX:UseAVX=1 after JDK-8380565 + - JDK-8381382: Shenandoah: assert(capacity > 0) failed: free regions must have allocation capacity + - JDK-8381519: Enhance Der Value Handling + - JDK-8381796: Enhance Certificate parsing + - JDK-8381871: GenShen: ShenandoahGCHeuristics flag not reset after ignoring non-adaptive value + - JDK-8381935: Improve numChunks range in the PPC64 CallAranger + - JDK-8381937: Make exceptions in Java_sun_security_mscapi_CKeyPairGenerator generateCKeyPair more specific + - JDK-8382018: test/jdk/java/nio/file/spi/SetDefaultProvider.java leaves a directory in /tmp + - JDK-8382020: Time Zone Abbreviation Not Localized for Non-English Locales + - JDK-8382035: [ubsan] Under UBSAN builds, disable tests that rely on simulated JVM crashes + - JDK-8382090: Remove .rej and .orig from .gitignore + - JDK-8382242: JFR: Metadata reconstruction invalidates ConstantMap for java.lang.String + - JDK-8382295: Shenandoah: wrong denominator in full gc summary + - JDK-8382395: Disable stringop-overflow in shenandoahGenerationalHeap.cpp + - JDK-8382419: Add missed @key randomness after JDK-8370489 + - JDK-8382522: Disable stringop-overflow in safepointMechanism.cpp + - JDK-8382740: JFR: Disable jdk.OldObjectSample event for generational ZGC + - JDK-8382878: RISC-V: Missing InlineSkippedInstructionsCounter in ZGC barriers stubs + - JDK-8382932: [25u] Test java/lang/instrument/RetransformRecordTypeAnn/TestRetransformRecord.java‎ fails with compilation error + - JDK-8383161: [PPC64] MachCallDynamicJavaNode::ret_addr_offset() needs adaptation for COH + - JDK-8383175: (tz) Update Timezone Data to 2026b + - JDK-8383183: Shenandoah: Mangle trashed regions up to top instead of end + - JDK-8383354: Update LCMS to 2.19.1 + - JDK-8383473: Follow on from tzdata2026b time change to include temporary hack BC time change + - JDK-8383601: RISC-V: ShenandoahBarrierSetAssembler::load_reference_barrier calls "weak" on "phantom" path + - JDK-8383630: Fix iteration in tests doing class redefinition + - JDK-8384043: [REDO] Incorrect handling of Hawaii_Aleutian metazone + - JDK-8384158: GHA: Downgrade Windows GHA runners to windows-2022 temporarily + - JDK-8384163: (so) SocketChannel.connect and finishConnect() exception messages could be improved + - JDK-8384223: RISC-V: entry_barrier_offset should consider UseZtso + - JDK-8384486: NTLM tests fail on Windows 11 and Windows Server 2025 + - JDK-8384495: Update Libpng to 1.6.58 + - JDK-8384540: [25u, 21u, 17u] Update GHA JDKs after Apr/26 updates + - JDK-8384815: SelectOneKeyOutOfMany and PreferredKey fail after expired test certificate + - JDK-8384902: Update GIFlib to 6.1.3 + - JDK-8385390: Update FreeType to 2.14.3 + - JDK-8385490: Update HarfBuzz to 14.2.0 + - JDK-8386551: Windows build broken because of MSys2/Make update + +Notes on individual issues: +=========================== + +hotspot/svc: + +JDK-8365057: Add support for java.util.concurrent lock information to Thread.dump_to_file +========================================================================================= +An AbstractOwnableSynchronizer lock object has a notion of exclusive +ownership by a particular thread. When another thread is parked +waiting on this lock, this information is now obtained and presented +as part of the thread dump provided by the +com.sun.management.HotSpotDiagnosticMXBean.dumpThreads API and the +`jcmd Thread.dump_to_file` command. + +security-libs/javax.crypto: + +JDK-8347938: Add Support for the Latest ML-KEM and ML-DSA Private Key Encodings +=============================================================================== + +This release of OpenJDK adds support for encoding ML-KEM and ML-DSA +keys to PKCS#8 format using the DER-encoded ASN.1 CHOICE formats +defined in Section 6, "Private Key Format" of RFC 9935 [0] and RFC +9881 [1]. This format is referred to as "seed". + +This release also introduces two new security and system properties to +control which PKCS#8 encoding is used. This encoding is used when +generating new keys with a `KeyPairGenerator` and as the output when +translating them with `KeyFactory.translateKey`. These properties are +`jdk.mlkem.pkcs8.encoding` and `jdk.mldsa.pkcs8.encoding`. + +The possible case-insensitive values of these properties are: + +* `seed`; the new format introduced in this release and the default. +This is 64 bytes for ML-KEM and 32 bytes for ML-DSA. +* `expandedKey`; the format used on introduction of ML-KEM and ML-DSA +keys in OpenJDK 24. +* `both`; a sequence containing both encodings. + +As older OpenJDK releases do not support the encoding introduced by +this release, they will not be able to decode keys generated using the +new default. To produce a key compatible with older releases, the +encoding should be set to `encodedKey` and then the key either +generated or an existing key passed to `translateKey`. + +As with all security and system property pairs, specifying a non-empty +value for the system property takes precedence over the security +property. + +[0] https://www.rfc-editor.org/rfc/rfc9935.html#name-private-key-format +[1] https://www.rfc-editor.org/rfc/rfc9881.html#name-private-key-format + +hotspot/jfr: + +JDK-8382740: JFR: Disable jdk.OldObjectSample event for generational ZGC +======================================================================== +Leak profiling using the JFR event `jdk.OldObjectSample` is now +disabled for generational ZGC due to performance issues. Generational +ZGC only does weak reference processing in the old generation, so +sampling will cause garbage to be artificially kept alive until an old +generation collection. + +security-libs/java.security: + +JDK-8372351: Add 2 WISeKey roots +================================ +The following root certificates have been added to the cacerts +truststore: + +Alias Name: wisekeyglobalrootgbca +Distinguished Name: CN=OISTE WISeKey Global Root GB CA, OU=OISTE Foundation Endorsed, O=WISeKey, C=CH +Serial Number: 76b1205274f0858746b3f8231af6c2c0 +Valid From: Mon Dec 01 15:00:32 GMT 2014 +Valid Until: Thu Dec 01 15:10:31 GMT 2039 + +Alias Name: wisekeyglobalrootgcca +Distinguished Name: CN=OISTE WISeKey Global Root GC CA, OU=OISTE Foundation Endorsed, O=WISeKey, C=CH +Serial Number: 212a560caeda0cab4045bf2ba22d3aea +Valid From: Tue May 09 09:48:34 GMT 2017 +Valid Until: Fri May 09 09:58:33 GMT 2042 + +JDK-8381796: Enhance Certificate parsing +======================================== +With this release of OpenJDK, a security and system property +`com.sun.security.crl.maxSize` is introduced which acts as a maximum +size limit on a Certificate Revocation List (CRL) downloaded over the +network. For URICertStore requests, the value is the maximum size in +bytes of the DER-encoded CRL. For LDAPCertStore queries, the +threshold is the sum of all CRLs downloaded from a single search. By +default, the maximum size is 20MiB (20971520 bytes) and CRLs larger +than this will be discarded. A value less than zero may be used to +turn off the size limit and non-numeric values will be ignored. A +non-empty value for the system property takes precedence over the +security property. Enabling 'certpath' debug logging will output the +current size limit and note any discarded CRLs. + New in release OpenJDK 25.0.3 (2026-04-21): =========================================== Live versions of these release notes can be found at: diff --git a/TestTranslations.java b/TestTranslations.java index 1b02c06..9e4002a 100644 --- a/TestTranslations.java +++ b/TestTranslations.java @@ -1,5 +1,5 @@ /* TestTranslations -- Ensure translations are available for new timezones - Copyright (C) 2022 Red Hat, Inc. + Copyright (C) 2026 Red Hat, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as @@ -50,25 +50,38 @@ public class TestTranslations { "Mountain Daylight Time", "MDT", "MDT", "Mountain Time", "MT", "MT"}); map.put(Locale.FRANCE, new String[] { "heure normale des Rocheuses", "UTC\u221207:00", "MST", - "heure d\u2019\u00e9t\u00e9 des Rocheuses", "UTC\u221206:00", "MST", - "heure des Rocheuses", "UTC\u221207:00", "MST"}); + "heure d\u2019\u00e9t\u00e9 des Rocheuses", "UTC\u221206:00", "MDT", + "heure des Rocheuses", "UTC\u221207:00", "MT"}); map.put(Locale.GERMANY, new String[] { "Rocky-Mountains-Normalzeit", "GMT-07:00", "MST", - "Rocky-Mountains-Sommerzeit", "GMT-06:00", "MST", - "Rocky-Mountains-Zeit", "GMT-07:00", "MST"}); + "Rocky-Mountains-Sommerzeit", "GMT-06:00", "MDT", + "Rocky-Mountains-Zeit", "GMT-07:00", "MT"}); CIUDAD_JUAREZ = Collections.unmodifiableMap(map); } public static void main(String[] args) { - if (args.length < 1) { - System.err.println("Test must be started with the name of the locale provider."); - System.exit(1); + boolean debug = false; + + if (args.length > 0) { + debug = Boolean.parseBoolean(args[0]); } + System.err.printf("Debugging: %s\n", debug); + + testZoneStrings(debug); + + testZone(KYIV, + new String[] { "Europe/Kiev", "Europe/Kyiv", "Europe/Uzhgorod", "Europe/Zaporozhye" }); + testZone(CIUDAD_JUAREZ, + new String[] { "America/Cambridge_Bay", "America/Ciudad_Juarez" }); + } + + private static void testZoneStrings(final boolean debug) { System.out.println("Checking sanity of full zone string set..."); boolean invalid = Arrays.stream(Locale.getAvailableLocales()) - .peek(l -> System.out.println("Locale: " + l)) + .peek(l -> System.out.printf(debug ? "Locale: %s\n" : "", l)) .map(l -> DateFormatSymbols.getInstance(l).getZoneStrings()) + .peek(df -> System.out.printf(debug ? "Zone string size: %s\n" : "", df.length)) .flatMap(zs -> Arrays.stream(zs)) .flatMap(names -> Arrays.stream(names)) .filter(name -> Objects.isNull(name) || name.isEmpty()) @@ -78,15 +91,9 @@ public class TestTranslations { System.err.println("Zone string for a locale returned null or empty string"); System.exit(2); } - - String localeProvider = args[0]; - testZone(localeProvider, KYIV, - new String[] { "Europe/Kiev", "Europe/Kyiv", "Europe/Uzhgorod", "Europe/Zaporozhye" }); - testZone(localeProvider, CIUDAD_JUAREZ, - new String[] { "America/Cambridge_Bay", "America/Ciudad_Juarez" }); } - private static void testZone(String localeProvider, Map exp, String[] ids) { + private static void testZone(Map exp, String[] ids) { for (Locale l : exp.keySet()) { String[] expected = exp.get(l); System.out.printf("Expected values for %s are %s\n", l, Arrays.toString(expected)); @@ -97,16 +104,11 @@ public class TestTranslations { System.out.printf("Checking locale %s for %s...\n", l, id); - if ("JRE".equals(localeProvider) || "CLDR".equals(localeProvider)) { - expectedShortStd = expected[2]; - expectedShortDST = expected[5]; - expectedShortGen = expected[8]; - } else { - System.err.printf("Invalid locale provider %s\n", localeProvider); - System.exit(3); - } - System.out.printf("Locale Provider is %s, using short values %s, %s and %s\n", - localeProvider, expectedShortStd, expectedShortDST, expectedShortGen); + expectedShortStd = expected[2]; + expectedShortDST = expected[5]; + expectedShortGen = expected[8]; + System.out.printf("Using short values %s, %s and %s\n", + expectedShortStd, expectedShortDST, expectedShortGen); String longStd = TimeZone.getTimeZone(id).getDisplayName(false, TimeZone.LONG, l); String shortStd = TimeZone.getTimeZone(id).getDisplayName(false, TimeZone.SHORT, l); diff --git a/java-25-openjdk-portable.specfile b/java-25-openjdk-portable.specfile index 54054b5..6eb9bfa 100644 --- a/java-25-openjdk-portable.specfile +++ b/java-25-openjdk-portable.specfile @@ -1,4 +1,97 @@ -# debug_package %%{nil} is portable-jdks specific +# New Version-String scheme-style defines +%global featurever 25 +%global interimver 0 +%global updatever 4 +%global patchver 0 +%global buildver 7 +%global portablerelease 1 +%global rpmrelease 0 + +# Define IcedTea version used for SystemTap tapsets and desktop file +%global icedteaver 6.0.0pre00-c848b93a8598 +# Define current Git revision for the FIPS support patches +%global fipsver 57722aab802 +# Define JDK versions +%global newjavaver %{featurever}.%{interimver}.%{updatever}.%{patchver} +%global javaver %{featurever} +# Strip up to 6 trailing zeros in newjavaver, as the JDK does, to get the correct version used in filenames +%global filever %(svn=%{newjavaver}; for i in 1 2 3 4 5 6 ; do svn=${svn%%.0} ; done; echo ${svn}) +# The tag used to create the OpenJDK tarball +%global vcstag jdk-%{filever}+%{buildver}%{?tagsuffix:-%{tagsuffix}} + +# Standard JPackage naming and versioning defines +%global origin openjdk +%global origin_nice OpenJDK +%global top_level_dir_name %{vcstag} +%global top_level_dir_name_backup %{top_level_dir_name}-backup +# Define an optional suffix for the OS this package is built on +%if 0%{?rhel} == 7 +%global pkgos rhel7 +%endif + +# Define milestone (EA for pre-releases, GA for releases) +# Release will be (where N is usually a number starting at 1): +# - 0.N.ea for EA releases, +# - N for GA releases +%global is_ga 1 +%if %{is_ga} +%global build_type GA +%global ea_designator "" +%global ea_designator_zip %{nil} +%global extraver %{nil} +%global eaprefix %{nil} +%else +%global build_type EA +%global ea_designator ea +%global ea_designator_zip -%{ea_designator} +%global extraver .%{ea_designator} +%global eaprefix 0. +%endif + +%global compatiblename java-%{javaver}-%{origin} + +Name: %{compatiblename}-portable%{?pkgos:-%{pkgos}} +Version: %{newjavaver}.%{buildver} +Release: %{?eaprefix}%{portablerelease}.%{rpmrelease}%{?extraver}%{?dist} + +%global fullversion %{compatiblename}-%{version}-%{release} + +# java-1.5.0-ibm from jpackage.org set Epoch to 1 for unknown reasons +# and this change was brought into RHEL-4. java-1.5.0-ibm packages +# also included the epoch in their virtual provides. This created a +# situation where in-the-wild java-1.5.0-ibm packages provided "java = +# 1:1.5.0". In RPM terms, "1.6.0 < 1:1.5.0" since 1.6.0 is +# interpreted as 0:1.6.0. So the "java >= 1.6.0" requirement would be +# satisfied by the 1:1.5.0 packages. Thus we need to set the epoch in +# JDK package >= 1.6.0 to 1, and packages referring to JDK virtual +# provides >= 1.6.0 must specify the epoch, "java >= 1:1.6.0". +Epoch: 1 +Summary: %{origin_nice} %{featurever} Runtime Environment portable edition +# Groups are only used up to RHEL 8 and on Fedora versions prior to F30 +%if (0%{?rhel} > 0 && 0%{?rhel} <= 8) || (0%{?fedora} >= 0 && 0%{?fedora} < 30) +Group: Development/Languages +%endif + +# HotSpot code is licensed under GPLv2 +# JDK library code is licensed under GPLv2 with the Classpath exception +# The Apache license is used in code taken from Apache projects (primarily xalan & xerces) +# DOM levels 2 & 3 and the XML digital signature schemas are licensed under the W3C Software License +# The JSR166 concurrency code is in the public domain +# The BSD and MIT licenses are used for a number of third-party libraries (see ADDITIONAL_LICENSE_INFO) +# The OpenJDK source tree includes: +# - JPEG library (IJG), zlib & libpng (zlib), giflib (MIT), harfbuzz (ISC), +# - freetype (FTL), jline (BSD) and LCMS (MIT) +# - jquery (MIT), jdk.crypto.cryptoki PKCS 11 wrapper (RSA) +# - public_suffix_list.dat from publicsuffix.org (MPLv2.0) +# The test code includes copies of NSS under the Mozilla Public License v2.0 +# The PCSClite headers are under a BSD with advertising license +# The elliptic curve cryptography (ECC) source code is licensed under the LGPLv2.1 or any later version +License: ASL 1.1 and ASL 2.0 and BSD and BSD with advertising and GPL+ and GPLv2 and GPLv2 with exceptions and IJG and LGPLv2+ and MIT and MPLv2.0 and Public Domain and W3C and zlib and ISC and FTL and RSA +URL: http://openjdk.java.net/ + +# We are producing RPMs containing only tarballs +# and checksums so there are no binaries outside +# the tarballs to be processed for debuginfo %define debug_package %{nil} # RPM conditionals so as to be able to dynamically produce @@ -96,25 +189,6 @@ %global normal_build %{nil} %endif -# We have hardcoded list of files, which is appearing in alternatives, and in files -# in alternatives those are slaves and master, very often triplicated by man pages -# in files all masters and slaves are ghosted -# the ghosts are here to allow installation via query like `dnf install /usr/bin/java` -# you can list those files, with appropriate sections: cat *.spec | grep -e --install -e --slave -e post_ -# TODO - fix those hardcoded lists via single list -# Those files must *NOT* be ghosted for *slowdebug* packages -# FIXME - if you are moving jshell or jlink or similar, always modify all three sections -# you can check via headless and devels: -# rpm -ql --noghost java-11-openjdk-headless-11.0.1.13-8.fc29.x86_64.rpm | grep bin -# == rpm -ql java-11-openjdk-headless-slowdebug-11.0.1.13-8.fc29.x86_64.rpm | grep bin -# != rpm -ql java-11-openjdk-headless-11.0.1.13-8.fc29.x86_64.rpm | grep bin -# similarly for other %%{_jvmdir}/{jre,java} and %%{_javadocdir}/{java,java-zip} -%define is_release_build() %( if [ "%{?1}" == "%{debug_suffix_unquoted}" -o "%{?1}" == "%{fastdebug_suffix_unquoted}" ]; then echo "0" ; else echo "1"; fi ) - -# while JDK is a techpreview(is_system_jdk=0), some provides are turned off. Once jdk stops to be an techpreview, move it to 1 -# as sytem JDK, we mean any JDK which can run whole system java stack without issues (like bytecode issues, module issues, dependencies...) -%global is_system_jdk 0 - %global aarch64 aarch64 arm64 armv8 # we need to distinguish between big and little endian PPC64 %global ppc64le ppc64le @@ -333,17 +407,14 @@ %global with_systemtap 0 %endif -# New Version-String scheme-style defines -%global featurever 25 -%global interimver 0 -%global updatever 3 -%global patchver 0 -# buildjdkver is usually same as %%{featurever}, -# but in time of bootstrap of next jdk, it is featurever-1, + +# buildjdkver is usually same as featurever, +# but at the time of bootstrap of the next jdk, it is featurever-1, # and this it is better to change it here, on single place %global buildjdkver %{featurever} + # We don't add any LTS designator for STS packages (Fedora and EPEL). -# We need to explicitly exclude EPEL as it would have the %%{rhel} macro defined. +# We need to explicitly exclude EPEL as it has the rhel macro defined. %if 0%{?rhel} && !0%{?epel} %global lts_designator "LTS" %global lts_designator_zip -%{lts_designator} @@ -355,7 +426,8 @@ # Define vendor information used by OpenJDK %global oj_vendor Red Hat, Inc. %global oj_vendor_url https://www.redhat.com/ -# Define what url should JVM offer in case of a crash report + +# Define what url the JVM should offer in case of a crash report # order may be important, epel may have rhel declared %if 0%{?epel} %global oj_vendor_bug_url https://bugzilla.redhat.com/enter_bug.cgi?product=Fedora%20EPEL&component=%{name}&version=epel%{epel} @@ -371,67 +443,13 @@ %endif %endif %endif -%global oj_vendor_version (Red_Hat-%{version}-%{rpmrelease}) +%global oj_vendor_version (Red_Hat-%{version}-%{portablerelease}) -# Define IcedTea version used for SystemTap tapsets and desktop file -%global icedteaver 6.0.0pre00-c848b93a8598 -# Define current Git revision for the FIPS support patches -%global fipsver 57722aab802 -# Define JDK versions -%global newjavaver %{featurever}.%{interimver}.%{updatever}.%{patchver} -%global javaver %{featurever} -# Strip up to 6 trailing zeros in newjavaver, as the JDK does, to get the correct version used in filenames -%global filever %(svn=%{newjavaver}; for i in 1 2 3 4 5 6 ; do svn=${svn%%.0} ; done; echo ${svn}) -# The tag used to create the OpenJDK tarball -%global vcstag jdk-%{filever}+%{buildver}%{?tagsuffix:-%{tagsuffix}} - -# Standard JPackage naming and versioning defines -%global origin openjdk -%global origin_nice OpenJDK -%global top_level_dir_name %{vcstag} -%global top_level_dir_name_backup %{top_level_dir_name}-backup -%global buildver 9 -%global rpmrelease 1 -#%%global tagsuffix %%{nil} -# Priority must be 8 digits in total; up to openjdk 1.8, we were using 18..... so when we moved to 11, we had to add another digit -%if %is_system_jdk -# Using 10 digits may overflow the int used for priority, so we combine the patch and build versions -# It is very unlikely we will ever have a patch version > 4 or a build version > 20, so we combine as (patch * 20) + build. -# This means 11.0.9.0+11 would have had a priority of 11000911 as before -# A 11.0.9.1+1 would have had a priority of 11000921 (20 * 1 + 1), thus ensuring it is bigger than 11.0.9.0+11 -%global combiver $( expr 20 '*' %{patchver} + %{buildver} ) -%global priority %( printf '%02d%02d%02d%02d' %{featurever} %{interimver} %{updatever} %{combiver} ) -%else -# for techpreview, using 1, so slowdebugs can have 0 -%global priority %( printf '%08d' 1 ) -%endif - -# Define milestone (EA for pre-releases, GA for releases) -# Release will be (where N is usually a number starting at 1): -# - 0.N%%{?extraver}%%{?dist} for EA releases, -# - N%%{?extraver}{?dist} for GA releases -%global is_ga 1 -%if %{is_ga} -%global build_type GA -%global ea_designator "" -%global ea_designator_zip %{nil} -%global extraver %{nil} -%global eaprefix %{nil} -%else -%global build_type EA -%global ea_designator ea -%global ea_designator_zip -%{ea_designator} -%global extraver .%{ea_designator} -%global eaprefix 0. -%endif - -# parametrized macros are order-sensitive -%global compatiblename java-%{featurever}-%{origin} -%global fullversion %{compatiblename}-%{version}-%{release} # images directories from upstream build %global jdkimage jdk %global static_libs_image static-libs-graal # output dir stub +# Parameterised macros are order-sensitive %define buildoutputdir() %{expand:build/jdk%{featurever}.build%{?1}} %define installoutputdir() %{expand:install/jdk%{featurever}.install%{?1}} %global altjavaoutputdir install/altjava.install @@ -442,20 +460,29 @@ %define uniquesuffix() %{expand:%{fullversion}.%{_arch}%{?1}} # portable only declarations %global jreimage jre -%define jreportablenameimpl() %(echo %{uniquesuffix ""} | sed "s;el%{rhel}\\(_[0-9]\\)*;portable%{1}.jre;g") -%define jdkportablenameimpl() %(echo %{uniquesuffix ""} | sed "s;el%{rhel}\\(_[0-9]\\)*;portable%{1}.jdk;g") -%define staticlibsportablenameimpl() %(echo %{uniquesuffix ""} | sed "s;el%{rhel}\\(_[0-9]\\)*;portable%{1}.static-libs;g") +%define jreportablenameimpl() %(echo %{uniquesuffix ""} | sed "s;el%{rhel}[^.]*;portable%{1}.jre;g") +%define jdkportablenameimpl() %(echo %{uniquesuffix ""} | sed "s;el%{rhel}[^.]*;portable%{1}.jdk;g") +%define staticlibsportablenameimpl() %(echo %{uniquesuffix ""} | sed "s;el%{rhel}[^.]*;portable%{1}.static-libs;g") + +# RPM 4.19 no longer accept our double percentaged %%{nil} passed to %%{1} +# so we have to pass in "" but evaluate it, otherwise files will include it %define jreportablearchive() %{expand:%{jreportablenameimpl -- %%{1}}.tar.xz} +%define jreportablearchive_for_files() %(echo %{jreportablearchive -- ""}) %define jdkportablearchive() %{expand:%{jdkportablenameimpl -- %%{1}}.tar.xz} +%define jdkportablearchive_for_files() %(echo %{jdkportablearchive -- ""}) %define staticlibsportablearchive() %{expand:%{staticlibsportablenameimpl -- %%{1}}.tar.xz} +%define staticlibsportablearchive_for_files() %(echo %{staticlibsportablearchive -- ""}) + %define jreportablename() %{expand:%{jreportablenameimpl -- %%{1}}} %define jdkportablename() %{expand:%{jdkportablenameimpl -- %%{1}}} -# Intentionally use jdkportablenameimpl here since we want to have static-libs files overlayed on -# top of the JDK archive +# We intentionally use jdkportablenameimpl here since we want to have +# static-libs files overlayed on top of the JDK archive %define staticlibsportablename() %{expand:%{jdkportablenameimpl -- %%{1}}} -%define docportablename() %(echo %{uniquesuffix ""} | sed "s;el%{rhel}\\(_[0-9]\\)*;portable.docs;g") + +# These macros are not parameterised as the same is shared by all builds +%define docportablename() %(echo %{uniquesuffix ""} | sed "s;el%{rhel}[^.]*;portable.docs;g") %define docportablearchive() %{docportablename}.tar.xz -%define miscportablename() %(echo %{uniquesuffix ""} | sed "s;el%{rhel}\\(_[0-9]\\)*;portable.misc;g") +%define miscportablename() %(echo %{uniquesuffix ""} | sed "s;el%{rhel}[^.]*;portable.misc;g") %define miscportablearchive() %{miscportablename}.tar.xz # JDK to use for bootstrapping @@ -474,26 +501,6 @@ %global build_hotspot_first 0 %endif -################################################################# -# fix for https://bugzilla.redhat.com/show_bug.cgi?id=1111349 -# https://bugzilla.redhat.com/show_bug.cgi?id=1590796#c14 -# https://bugzilla.redhat.com/show_bug.cgi?id=1655938 -%global _privatelibs libsplashscreen[.]so.*|libawt_xawt[.]so.*|libjli[.]so.*|libattach[.]so.*|libawt[.]so.*|libextnet[.]so.*|libawt_headless[.]so.*|libdt_socket[.]so.*|libfontmanager[.]so.*|libinstrument[.]so.*|libj2gss[.]so.*|libj2pcsc[.]so.*|libj2pkcs11[.]so.*|libjaas[.]so.*|libjavajpeg[.]so.*|libjdwp[.]so.*|libjimage[.]so.*|libjsound[.]so.*|liblcms[.]so.*|libmanagement[.]so.*|libmanagement_agent[.]so.*|libmanagement_ext[.]so.*|libmlib_image[.]so.*|libnet[.]so.*|libnio[.]so.*|libprefs[.]so.*|librmi[.]so.*|libsaproc[.]so.*|libsctp[.]so.*|libsystemconf[.]so.*|libzip[.]so.*%{freetype_lib} -%global _publiclibs libjawt[.]so.*|libjava[.]so.*|libjvm[.]so.*|libverify[.]so.*|libjsig[.]so.* -%if %is_system_jdk -%global __provides_exclude ^(%{_privatelibs})$ -%global __requires_exclude ^(%{_privatelibs})$ -# Never generate lib-style provides/requires for slowdebug packages -%global __provides_exclude_from ^.*/%{uniquesuffix -- %{debug_suffix_unquoted}}/.*$ -%global __requires_exclude_from ^.*/%{uniquesuffix -- %{debug_suffix_unquoted}}/.*$ -%global __provides_exclude_from ^.*/%{uniquesuffix -- %{fastdebug_suffix_unquoted}}/.*$ -%global __requires_exclude_from ^.*/%{uniquesuffix -- %{fastdebug_suffix_unquoted}}/.*$ -%else -# Don't generate provides/requires for JDK provided shared libraries at all. -%global __provides_exclude ^(%{_privatelibs}|%{_publiclibs})$ -%global __requires_exclude ^(%{_privatelibs}|%{_publiclibs})$ -%endif - # VM variant being built %ifarch %{zero_arches} %global vm_variant zero @@ -501,28 +508,11 @@ %global vm_variant server %endif -%global etcjavasubdir %{_sysconfdir}/java/java-%{javaver}-%{origin} -%define etcjavadir() %{expand:%{etcjavasubdir}/%{uniquesuffix -- %{?1}}} -# Standard JPackage directories and symbolic links. -%define sdkdir() %{expand:%{uniquesuffix -- %{?1}}} -%define jrelnk() %{expand:jre-%{javaver}-%{origin}-%{version}-%{release}.%{_arch}%{?1}} - -%define sdkbindir() %{expand:%{_jvmdir}/%{sdkdir -- %{?1}}/bin} -%define jrebindir() %{expand:%{_jvmdir}/%{sdkdir -- %{?1}}/bin} - %global alt_java_name alt-java %global devkit_name %{origin}-devkit %global rpm_state_dir %{_localstatedir}/lib/rpm-state/ -# For flatpack builds hard-code /usr/sbin/alternatives, -# otherwise use %%{_sbindir} relative path. -%if 0%{?flatpak} -%global alternatives_requires /usr/sbin/alternatives -%else -%global alternatives_requires %{_sbindir}/alternatives -%endif - # Portables have no repo (requires/provides), but these are awesome for orientation in spec # Also scriptlets are happily missing and files are handled old fashion # not-duplicated requires/provides/obsoletes for normal/debug packages @@ -547,11 +537,6 @@ # Prevent brp-java-repack-jars from being run %global __jar_repack 0 -# Define an optional suffix for the OS this package is built on -%if 0%{?rhel} == 7 -%global pkgos rhel7 -%endif - # Define the architectures on which we build # On RHEL, this should be the architectures with a devkit %if 0%{?centos} == 0 @@ -560,43 +545,6 @@ ExclusiveArch: %{devkit_arches} ExclusiveArch: %{aarch64} %{ppc64le} s390x x86_64 riscv64 %endif -Name: java-%{javaver}-%{origin}-portable%{?pkgos:-%{pkgos}} -Version: %{newjavaver}.%{buildver} -Release: %{?eaprefix}%{rpmrelease}%{?extraver}%{?dist} -# java-1.5.0-ibm from jpackage.org set Epoch to 1 for unknown reasons -# and this change was brought into RHEL-4. java-1.5.0-ibm packages -# also included the epoch in their virtual provides. This created a -# situation where in-the-wild java-1.5.0-ibm packages provided "java = -# 1:1.5.0". In RPM terms, "1.6.0 < 1:1.5.0" since 1.6.0 is -# interpreted as 0:1.6.0. So the "java >= 1.6.0" requirement would be -# satisfied by the 1:1.5.0 packages. Thus we need to set the epoch in -# JDK package >= 1.6.0 to 1, and packages referring to JDK virtual -# provides >= 1.6.0 must specify the epoch, "java >= 1:1.6.0". - -Epoch: 1 -Summary: %{origin_nice} %{featurever} Runtime Environment portable edition -# Groups are only used up to RHEL 8 and on Fedora versions prior to F30 -%if (0%{?rhel} > 0 && 0%{?rhel} <= 8) || (0%{?fedora} >= 0 && 0%{?fedora} < 30) -Group: Development/Languages -%endif - -# HotSpot code is licensed under GPLv2 -# JDK library code is licensed under GPLv2 with the Classpath exception -# The Apache license is used in code taken from Apache projects (primarily xalan & xerces) -# DOM levels 2 & 3 and the XML digital signature schemas are licensed under the W3C Software License -# The JSR166 concurrency code is in the public domain -# The BSD and MIT licenses are used for a number of third-party libraries (see ADDITIONAL_LICENSE_INFO) -# The OpenJDK source tree includes: -# - JPEG library (IJG), zlib & libpng (zlib), giflib (MIT), harfbuzz (ISC), -# - freetype (FTL), jline (BSD) and LCMS (MIT) -# - jquery (MIT), jdk.crypto.cryptoki PKCS 11 wrapper (RSA) -# - public_suffix_list.dat from publicsuffix.org (MPLv2.0) -# The test code includes copies of NSS under the Mozilla Public License v2.0 -# The PCSClite headers are under a BSD with advertising license -# The elliptic curve cryptography (ECC) source code is licensed under the LGPLv2.1 or any later version -License: ASL 1.1 and ASL 2.0 and BSD and BSD with advertising and GPL+ and GPLv2 and GPLv2 with exceptions and IJG and LGPLv2+ and MIT and MPLv2.0 and Public Domain and W3C and zlib and ISC and FTL and RSA -URL: http://openjdk.java.net/ - # The source tarball, generated using generate_source_tarball.sh Source0: https://openjdk-sources.osci.io/openjdk%{featurever}/open%{vcstag}%{ea_designator_zip}.tar.xz @@ -638,10 +586,13 @@ Source18: TestTranslations.java # RPM/distribution specific patches # ############################################ + # Crypto policy and FIPS support patches + # Patch is generated from the fips-25u tree at https://github.com/rh-openjdk/jdk/tree/fips-25u -# as follows: git diff %%{vcstag} src make test > fips-25u-$(git show -s --format=%h HEAD).patch +# as follows: git diff src make test > fips-25u-$(git show -s --format=%h HEAD).patch # Diff is limited to src and make subdirectories to exclude .github changes + # Fixes currently included: # OPENJDK-2108: Internal __redhat_fips__ property # OPENJDK-2123: Algorithms lockdown @@ -662,8 +613,10 @@ Patch1001: fips-%{featurever}u-%{fipsver}.patch # ############################################# -# JDK-8375294: (fs) Files.copy can fail with EOPNOTSUPP when copy_file_range not supported -Patch2001: jdk8375294-handle-EOPNOTSUPP-in-copying.patch +# JDK-8347901: C2 should remove unused leaf / pure runtime calls +Patch2002: jdk8347901-c2_unused_leaf_removal.patch +# JDK-83787313: C2: performance regression due to missing constant folding for Math.pow() +Patch2003: jdk8378713-c2_missing_pow_constant_folding.patch ############################################# # @@ -746,17 +699,17 @@ BuildRequires: libpng-devel BuildRequires: zlib-devel %else # Version in src/java.desktop/share/legal/freetype.md -Provides: bundled(freetype) = 2.14.2 +Provides: bundled(freetype) = 2.14.3 # Version in src/java.desktop/share/native/libsplashscreen/giflib/gif_lib.h -Provides: bundled(giflib) = 6.1.2 +Provides: bundled(giflib) = 6.1.3 # Version in src/java.desktop/share/native/libharfbuzz/hb-version.h -Provides: bundled(harfbuzz) = 12.3.2 +Provides: bundled(harfbuzz) = 14.2.0 # Version in src/java.desktop/share/native/liblcms/lcms2.h -Provides: bundled(lcms2) = 2.17.0 +Provides: bundled(lcms2) = 2.19.1 # Version in src/java.desktop/share/native/libjavajpeg/jpeglib.h Provides: bundled(libjpeg) = 6b # Version in src/java.desktop/share/native/libsplashscreen/libpng/png.h -Provides: bundled(libpng) = 1.6.57 +Provides: bundled(libpng) = 1.6.58 # Version in src/java.base/share/native/libzip/zlib/zlib.h Provides: bundled(zlib) = 1.3.2 # We link statically against libstdc++ to increase portability @@ -947,11 +900,6 @@ fi export XZ_OPT="-T0" %setup -q -c -n %{uniquesuffix ""} -T -a 0 # https://bugzilla.redhat.com/show_bug.cgi?id=1189084 -prioritylength=`expr length %{priority}` -if [ $prioritylength -ne 8 ] ; then - echo "priority must be 8 digits in total, violated" - exit 14 -fi # OpenJDK patches @@ -961,24 +909,13 @@ sh %{SOURCE12} %{top_level_dir_name} %endif # Patch the JDK -# This syntax is deprecated: -# %patchN [...] -# and should be replaced with: -# %patch -PN [...] -# For example: -# %patch1001 -p1 -# becomes: -# %patch -P1001 -p1 -# The replacement format suggested by recent (circa Fedora 38) RPM -# deprecation messages: -# %patch N [...] -# is not backward-compatible with prior (circa RHEL-8) versions of -# rpmbuild. + pushd %{top_level_dir_name} # Add crypto policy and FIPS support %patch -P1001 -p1 -# Add EOPNOTSUPP patch -%patch -P2001 -p1 +# Add C2 patches +%patch -P2002 -p1 +%patch -P2003 -p1 popd # openjdk echo "Generating %{alt_java_name} man page" @@ -1062,7 +999,6 @@ cat %{bootjdk}/release export NUM_PROC=%(/usr/bin/getconf _NPROCESSORS_ONLN 2> /dev/null || :) export NUM_PROC=${NUM_PROC:-1} %if 0%{?_smp_ncpus_max} -# Honor %%_smp_ncpus_max [ ${NUM_PROC} -gt %{?_smp_ncpus_max} ] && export NUM_PROC=%{?_smp_ncpus_max} %endif export XZ_OPT="-T0" @@ -1182,8 +1118,8 @@ function buildjdk() { mkdir -p ${outputdir} pushd ${outputdir} - # Note: zlib and freetype use %{link_type} - # rather than ${link_opt} as the system versions + # Note: zlib and freetype use link_type (macro) + # rather than link_opt (shell var) as the system versions # are always used in a system_libs build, even # for the static library build LD_LIBRARY_PATH=${LIBPATH} \ @@ -1692,10 +1628,7 @@ $JAVA_HOME/bin/java -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -versi # Check translations are available for new timezones (during flatpak builds, the # tzdb.dat used by this test is not where the test expects it, so this is # disabled for flatpak builds) - # Disable test until we are on the latest JDK - $JAVA_HOME/bin/javac -d . %{SOURCE18} - $JAVA_HOME/bin/java $(echo $(basename %{SOURCE18})|sed "s|\.java||") JRE - $JAVA_HOME/bin/java -Djava.locale.providers=CLDR $(echo $(basename %{SOURCE18})|sed "s|\.java||") CLDR + $JAVA_HOME/bin/java %{SOURCE18} %endif # Check blocked.certs is valid (OPENJDK-4362) @@ -1874,8 +1807,8 @@ done %files # main package builds always -%{_jvmdir}/%{jreportablearchive -- %%{nil}} -%{_jvmdir}/%{jreportablearchive -- %%{nil}}.sha256sum +%{_jvmdir}/%{jreportablearchive_for_files} +%{_jvmdir}/%{jreportablearchive_for_files}.sha256sum %else %files # placeholder @@ -1884,15 +1817,15 @@ done %if %{include_normal_build} %files devel -%{_jvmdir}/%{jdkportablearchive -- %%{nil}} +%{_jvmdir}/%{jdkportablearchive_for_files} %{_jvmdir}/%{jdkportablearchive -- .debuginfo} -%{_jvmdir}/%{jdkportablearchive -- %%{nil}}.sha256sum +%{_jvmdir}/%{jdkportablearchive_for_files}.sha256sum %{_jvmdir}/%{jdkportablearchive -- .debuginfo}.sha256sum %if %{include_staticlibs} %files static-libs -%{_jvmdir}/%{staticlibsportablearchive -- %%{nil}} -%{_jvmdir}/%{staticlibsportablearchive -- %%{nil}}.sha256sum +%{_jvmdir}/%{staticlibsportablearchive_for_files} +%{_jvmdir}/%{staticlibsportablearchive_for_files}.sha256sum %endif %files unstripped @@ -1946,6 +1879,48 @@ done %endif %changelog +* Thu Jul 16 2026 Andrew Hughes - 1:25.0.4.0.7-1.0 +- Update to jdk-25.0.4+7 (GA) +- Update release notes to 25.0.4+7 +- Bump freetype version to 2.14.3 following JDK-8385390 +- Bump giflib version to 6.1.3 following JDK-8384902 +- Bump HarfBuzz version to 14.2.0 following JDK-8385490 +- Bump lcms2 version to 2.19.1 following JDK-8375065 & JDK-8383354 +- Bump libpng version to 1.6.58 following JDK-8384495 +- Drop local copy of JDK-8375294 EOPNOTSUPP patch +- Revert fr_FR and de_DE changes made in d43f0e6186370fdeb0ca2f3594f39783e20eef1c now JDK-8382020 is fixed +- Simplify TestTranslations run now there is only the CLDR provider and one set of data (JDK-8174269) +- Make zone string debug output optional in TestTranslations +- ** This tarball is embargoed until 2026-07-21 @ 1pm PT. ** +- Resolves: OPENJDK-4865 +- Resolves: OPENJDK-4902 + +* Mon Jul 13 2026 Andrew Hughes - 1:25.0.3.0.9-3.0 +- Add 25u backports of JDK-8347901 & JDK-8378713 C2 performance fixes +- Resolves: OPENJDK-4885 + +* Thu Jul 02 2026 Andrea Bolognani - 1:25.0.3.0.9-3.0 +- Strip %%{dist} more thoroughly +- Resolves: OPENJDK-4881 + +* Fri Jun 26 2026 Andrew Hughes - 1:25.0.3.0.9-2.0 +- Port ForFiles patch to RHEL and update to use standard function naming format +- Remove macro references in comments where possible (%dnl not compatible enough yet) +- Drop unused tagsuffix line which causes issues on older RPM versions without %dnl +- Cleanup RPM only macros unused in the portable spec file +- Move version information and core NVR definitions back towards the top of the file +- Specify portablerelease and rpmrelease (always 0 for portables) in the Release field +- Related: OPENJDK-4872 +- Resolves: OPENJDK-4873 +- Resolves: OPENJDK-4875 +- Resolves: OPENJDK-4876 + +* Fri Jun 26 2026 Jiri Vanek - 1:25.0.3.0.9-2 +- Redeclared ForFiles release sections as %%nil no longer works with %%1 +- RPM 4.19 no longer accept our double percentaged %%{nil} passed to %%{1} +- so we have to pass in "" but evaluate it, otherwise files record will include it +- Resolves: OPENJDK-4872 + * Sat Apr 18 2026 Andrew Hughes - 1:25.0.3.0.9-1 - Update to jdk-25.0.3+9 (GA) - Update release notes to 25.0.3+9 diff --git a/java-25-openjdk.spec b/java-25-openjdk.spec index 8a9b364..29ba2a3 100644 --- a/java-25-openjdk.spec +++ b/java-25-openjdk.spec @@ -3,6 +3,124 @@ # it and then adjust portablerelease and portablesuffix # to match the new portable. +# New Version-String scheme-style defines +%global featurever 25 +%global interimver 0 +%global updatever 4 +%global patchver 0 +%global buildver 7 +%global portablerelease 1 +%global rpmrelease 1 + +# Define IcedTea version used for SystemTap tapsets and desktop file +%global icedteaver 6.0.0pre00-c848b93a8598 +# Define current Git revision for the FIPS support patches +%global fipsver 57722aab802 +# Define nssadapter variables +%global nssadapter_version 0.1.1 +%global nssadapter_name nssadapter-%{nssadapter_version} +# Define whether the crypto policy is expected to be active when testing +%global crypto_policy_active true +# Define JDK versions +%global newjavaver %{featurever}.%{interimver}.%{updatever}.%{patchver} +%global javaver %{featurever} +# Strip up to 6 trailing zeros in newjavaver, as the JDK does, to get the correct version used in filenames +%global filever %(svn=%{newjavaver}; for i in 1 2 3 4 5 6 ; do svn=${svn%%.0} ; done; echo ${svn}) +# The tag used to create the OpenJDK tarball +%global vcstag jdk-%{filever}+%{buildver}%{?tagsuffix:-%{tagsuffix}} + +# Standard JPackage naming and versioning defines +%global origin openjdk +%global origin_nice OpenJDK +%global top_level_dir_name %{vcstag} +%global top_level_dir_name_backup %{top_level_dir_name}-backup + +# Define milestone (EA for pre-releases, GA for releases) +# Release will be (where N is usually a number starting at 1): +# - 0.N.ea for EA releases, +# - N for GA releases +%global is_ga 1 +%if %{is_ga} +%global build_type GA +%global ea_designator "" +%global ea_designator_zip %{nil} +%global extraver %{nil} +%global eaprefix %{nil} +%else +%global build_type EA +%global ea_designator ea +%global ea_designator_zip -%{ea_designator} +%global extraver .%{ea_designator} +%global eaprefix 0. +%endif + +%global compatiblename java-%{javaver}-%{origin} + +Name: %{compatiblename} +Version: %{newjavaver}.%{buildver} +Release: %{?eaprefix}%{portablerelease}.%{rpmrelease}%{?extraver}%{?dist} + +%global fullversion %{compatiblename}-%{version}-%{release} + +# java-1.5.0-ibm from jpackage.org set Epoch to 1 for unknown reasons +# and this change was brought into RHEL-4. java-1.5.0-ibm packages +# also included the epoch in their virtual provides. This created a +# situation where in-the-wild java-1.5.0-ibm packages provided "java = +# 1:1.5.0". In RPM terms, "1.6.0 < 1:1.5.0" since 1.6.0 is +# interpreted as 0:1.6.0. So the "java >= 1.6.0" requirement would be +# satisfied by the 1:1.5.0 packages. Thus we need to set the epoch in +# JDK package >= 1.6.0 to 1, and packages referring to JDK virtual +# provides >= 1.6.0 must specify the epoch, "java >= 1:1.6.0". +Epoch: 1 +Summary: %{origin_nice} %{featurever} Runtime Environment +# Groups are only used up to RHEL 8 and on Fedora versions prior to F30 +%if (0%{?rhel} > 0 && 0%{?rhel} <= 8) || (0%{?fedora} >= 0 && 0%{?fedora} < 30) +Group: Development/Languages +%endif + +# HotSpot code is licensed under GPLv2 +# JDK library code is licensed under GPLv2 with the Classpath exception +# The Apache license is used in code taken from Apache projects (primarily xalan & xerces) +# DOM levels 2 & 3 and the XML digital signature schemas are licensed under the W3C Software License +# The JSR166 concurrency code is in the public domain +# The BSD and MIT licenses are used for a number of third-party libraries (see ADDITIONAL_LICENSE_INFO) +# The OpenJDK source tree includes: +# - JPEG library (IJG), zlib & libpng (zlib), giflib (MIT), harfbuzz (ISC), +# - freetype (FTL), jline (BSD) and LCMS (MIT) +# - jquery (MIT), jdk.crypto.cryptoki PKCS 11 wrapper (RSA) +# - public_suffix_list.dat from publicsuffix.org (MPLv2.0) +# The test code includes copies of NSS under the Mozilla Public License v2.0 +# The PCSClite headers are under a BSD with advertising license +# The elliptic curve cryptography (ECC) source code is licensed under the LGPLv2.1 or any later version +License: ASL 1.1 and ASL 2.0 and BSD and BSD with advertising and GPL+ and GPLv2 and GPLv2 with exceptions and IJG and LGPLv2+ and MIT and MPLv2.0 and Public Domain and W3C and zlib and ISC and FTL and RSA +URL: http://openjdk.java.net/ + +# Define the OS the portable JDK is built on +# This is undefined for CentOS & openjdk-portable-rhel-8 builds and +# equals 'rhel7' for openjdk-portable-rhel-7 builds +%if 0 +%global pkgos rhel7 +%endif +# Define the root name of the portable packages +%global pkgnameroot java-%{featurever}-%{origin}-portable%{?pkgos:-%{pkgos}} +# Release field for the portable build +# The rpmrelease field is always zero for portables +%global prelease %{?eaprefix}%{portablerelease}.0%{?extraver} +# Portable suffix differs between RHEL and CentOS +%if 0%{?centos} == 0 +%global portablerhel %{?pkgos:7_9}%{!?pkgos:8} +%else +%global portablerhel 9 +%endif +%global portablebuilddir /builddir/build/BUILD +%global portablesuffix el%{portablerhel} +# Check if pandoc was available to generate docs (including man pages) +%if 0%{?portablerhel} == 8 +%global pandoc_available 1 +%else +%global pandoc_available 0 +%endif + # RPM conditionals so as to be able to dynamically produce # slowdebug/release builds. See: # http://rpm.org/user_doc/conditional_builds.html @@ -87,19 +205,20 @@ %global normal_build %{nil} %endif -# We have hardcoded list of files, which is appearing in alternatives, and in files -# in alternatives those are slaves and master, very often triplicated by man pages -# in files all masters and slaves are ghosted -# the ghosts are here to allow installation via query like `dnf install /usr/bin/java` -# you can list those files, with appropriate sections: cat *.spec | grep -e --install -e --slave -e post_ -e alternatives +# We have a hardcoded list of files, which appears in alternatives and in files +# In alternatives, those are slaves and master, very often triplicated by man pages +# In files, all masters and slaves are ghosted +# The ghosts are here to allow installation via query like `dnf install /usr/bin/java` +# You can list those files, with appropriate sections: cat *.spec | grep -e --install -e --slave -e post_ -e alternatives # TODO - fix those hardcoded lists via single list -# Those files must *NOT* be ghosted for *slowdebug* packages +# Those files must *NOT* be ghosted for *debug* packages # FIXME - if you are moving jshell or jlink or similar, always modify all three sections -# you can check via headless and devels: +# You can check via headless and devels: # rpm -ql --noghost java-11-openjdk-headless-11.0.1.13-8.fc29.x86_64.rpm | grep bin # == rpm -ql java-11-openjdk-headless-slowdebug-11.0.1.13-8.fc29.x86_64.rpm | grep bin # != rpm -ql java-11-openjdk-headless-11.0.1.13-8.fc29.x86_64.rpm | grep bin -# similarly for other %%{_jvmdir}/{jre,java} and %%{_javadocdir}/{java,java-zip} +# and similarly for other packages. + %define is_release_build() %( if [ "%{?1}" == "%{debug_suffix_unquoted}" -o "%{?1}" == "%{fastdebug_suffix_unquoted}" ]; then echo "0" ; else echo "1"; fi ) # Indicates whether this is the default JDK on this version of RHEL @@ -283,13 +402,8 @@ %global with_systemtap 0 %endif -# New Version-String scheme-style defines -%global featurever 25 -%global interimver 0 -%global updatever 3 -%global patchver 0 # We don't add any LTS designator for STS packages (Fedora and EPEL). -# We need to explicitly exclude EPEL as it would have the %%{rhel} macro defined. +# We need to explicitly exclude EPEL as it has the rhel macro defined. %if 0%{?rhel} && !0%{?epel} %global lts_designator "LTS" %global lts_designator_zip -%{lts_designator} @@ -301,7 +415,8 @@ # Define vendor information used by OpenJDK %global oj_vendor Red Hat, Inc. %global oj_vendor_url https://www.redhat.com/ -# Define what url should JVM offer in case of a crash report + +# Define what url the JVM should offer in case of a crash report # order may be important, epel may have rhel declared %if 0%{?epel} %global oj_vendor_bug_url https://bugzilla.redhat.com/enter_bug.cgi?product=Fedora%20EPEL&component=%{name}&version=epel%{epel} @@ -319,54 +434,6 @@ %endif %global oj_vendor_version (Red_Hat-%{version}-%{portablerelease}) -# Define IcedTea version used for SystemTap tapsets and desktop file -%global icedteaver 6.0.0pre00-c848b93a8598 -# Define current Git revision for the FIPS support patches -%global fipsver 57722aab802 -# Define nssadapter variables -%global nssadapter_version 0.1.1 -%global nssadapter_name nssadapter-%{nssadapter_version} -# Define whether the crypto policy is expected to be active when testing -%global crypto_policy_active true -# Define JDK versions -%global newjavaver %{featurever}.%{interimver}.%{updatever}.%{patchver} -%global javaver %{featurever} -# Strip up to 6 trailing zeros in newjavaver, as the JDK does, to get the correct version used in filenames -%global filever %(svn=%{newjavaver}; for i in 1 2 3 4 5 6 ; do svn=${svn%%.0} ; done; echo ${svn}) -# The tag used to create the OpenJDK tarball -%global vcstag jdk-%{filever}+%{buildver}%{?tagsuffix:-%{tagsuffix}} - -# Define the OS the portable JDK is built on -# This is undefined for CentOS & openjdk-portable-rhel-8 builds and -# equals 'rhel7' for openjdk-portable-rhel-7 builds -%if 0 -%global pkgos rhel7 -%endif - -# Standard JPackage naming and versioning defines -%global origin openjdk -%global origin_nice OpenJDK -%global top_level_dir_name %{vcstag} -%global top_level_dir_name_backup %{top_level_dir_name}-backup -%global buildver 9 -%global rpmrelease 1 -# Settings used by the portable build -%global portablerelease 1 -# Portable suffix differs between RHEL and CentOS -%if 0%{?centos} == 0 -%global portablerhel %{?pkgos:7_9}%{!?pkgos:8} -%else -%global portablerhel 9 -%endif -%global portablebuilddir /builddir/build/BUILD -%global portablesuffix el%{portablerhel} -# Check if pandoc was available to generate docs (including man pages) -%if 0%{?portablerhel} == 8 -%global pandoc_available 1 -%else -%global pandoc_available 0 -%endif - # Priority must be 8 digits in total; up to openjdk 1.8, we were using 18..... so when we moved to 11, we had to add another digit %if %is_system_jdk # Using 10 digits may overflow the int used for priority, so we combine the patch and build versions @@ -380,29 +447,6 @@ %global priority %( printf '%08d' 1 ) %endif -# Define milestone (EA for pre-releases, GA for releases) -# Release will be (where N is usually a number starting at 1): -# - 0.N%%{?extraver}%%{?dist} for EA releases, -# - N%%{?extraver}{?dist} for GA releases -%global is_ga 1 -%if %{is_ga} -%global build_type GA -%global ea_designator "" -%global ea_designator_zip %{nil} -%global extraver %{nil} -%global eaprefix %{nil} -%else -%global build_type EA -%global ea_designator ea -%global ea_designator_zip -%{ea_designator} -%global extraver .%{ea_designator} -%global eaprefix 0. -%endif - -# parametrized macros are order-sensitive -%global compatiblename java-%{featurever}-%{origin} -%global fullversion %{compatiblename}-%{version}-%{release} -# output dir stub %define installoutputdir() %{expand:install/jdk%{featurever}.install%{?1}} # we can copy the javadoc to not arched dir, or make it not noarch %define uniquejavadocdir() %{expand:%{compatiblename}%{?1}} @@ -448,7 +492,7 @@ %global rpm_state_dir %{_localstatedir}/lib/rpm-state/ # For flatpack builds hard-code /usr/sbin/alternatives, -# otherwise use %%{_sbindir} relative path. +# otherwise use _sbindir relative path. %if 0%{?flatpak} %global alternatives_requires /usr/sbin/alternatives %else @@ -1121,8 +1165,8 @@ Requires: ca-certificates # Require javapackages-filesystem for ownership of /usr/lib/jvm/ and macros Requires: javapackages-filesystem # Require zone-info data provided by tzdata-java sub-package -# 2026a required as of JDK-8379035 -Requires: tzdata-java >= 2026a +# 2026b required as of JDK-8383175 +Requires: tzdata-java >= 2026b # for support of kernel stream control # libsctp.so.1 is being `dlopen`ed on demand Requires: lksctp-tools%{?_isa} @@ -1243,51 +1287,10 @@ Provides: java-%{origin}-src%{?1} = %{epoch}:%{version}-%{release} # Prevent brp-java-repack-jars from being run %global __jar_repack 0 -# Define the root name of the portable packages -%global pkgnameroot java-%{featurever}-%{origin}-portable%{?pkgos:-%{pkgos}} # Define the architectures on which we build ExclusiveArch: %{aarch64} %{ppc64le} s390x x86_64 riscv64 -Name: java-%{javaver}-%{origin} -Version: %{newjavaver}.%{buildver} -Release: %{?eaprefix}%{rpmrelease}%{?extraver}%{?dist} -# Equivalent for the portable build -%global prelease %{?eaprefix}%{portablerelease}%{?extraver} -# java-1.5.0-ibm from jpackage.org set Epoch to 1 for unknown reasons -# and this change was brought into RHEL-4. java-1.5.0-ibm packages -# also included the epoch in their virtual provides. This created a -# situation where in-the-wild java-1.5.0-ibm packages provided "java = -# 1:1.5.0". In RPM terms, "1.6.0 < 1:1.5.0" since 1.6.0 is -# interpreted as 0:1.6.0. So the "java >= 1.6.0" requirement would be -# satisfied by the 1:1.5.0 packages. Thus we need to set the epoch in -# JDK package >= 1.6.0 to 1, and packages referring to JDK virtual -# provides >= 1.6.0 must specify the epoch, "java >= 1:1.6.0". - -Epoch: 1 -Summary: %{origin_nice} %{featurever} Runtime Environment -# Groups are only used up to RHEL 8 and on Fedora versions prior to F30 -%if (0%{?rhel} > 0 && 0%{?rhel} <= 8) || (0%{?fedora} >= 0 && 0%{?fedora} < 30) -Group: Development/Languages -%endif - -# HotSpot code is licensed under GPLv2 -# JDK library code is licensed under GPLv2 with the Classpath exception -# The Apache license is used in code taken from Apache projects (primarily xalan & xerces) -# DOM levels 2 & 3 and the XML digital signature schemas are licensed under the W3C Software License -# The JSR166 concurrency code is in the public domain -# The BSD and MIT licenses are used for a number of third-party libraries (see ADDITIONAL_LICENSE_INFO) -# The OpenJDK source tree includes: -# - JPEG library (IJG), zlib & libpng (zlib), giflib (MIT), harfbuzz (ISC), -# - freetype (FTL), jline (BSD) and LCMS (MIT) -# - jquery (MIT), jdk.crypto.cryptoki PKCS 11 wrapper (RSA) -# - public_suffix_list.dat from publicsuffix.org (MPLv2.0) -# The test code includes copies of NSS under the Mozilla Public License v2.0 -# The PCSClite headers are under a BSD with advertising license -# The elliptic curve cryptography (ECC) source code is licensed under the LGPLv2.1 or any later version -License: ASL 1.1 and ASL 2.0 and BSD and BSD with advertising and GPL+ and GPLv2 and GPLv2 with exceptions and IJG and LGPLv2+ and MIT and MPLv2.0 and Public Domain and W3C and zlib and ISC and FTL and RSA -URL: http://openjdk.java.net/ - # The source tarball, generated using generate_source_tarball.sh Source0: https://openjdk-sources.osci.io/openjdk%{featurever}/open%{vcstag}%{ea_designator_zip}.tar.xz @@ -1367,9 +1370,11 @@ Source32: create-redhat-properties-files.bash ############################################ # Crypto policy and FIPS support patches + # Patch is generated from the fips-25u tree at https://github.com/rh-openjdk/jdk/tree/fips-25u -# as follows: git diff %%{vcstag} src make test > fips-25u-$(git show -s --format=%h HEAD).patch +# as follows: git diff src make test > fips-25u-$(git show -s --format=%h HEAD).patch # Diff is limited to src and make subdirectories to exclude .github changes + # Fixes currently included: # OPENJDK-2108: Internal __redhat_fips__ property # OPENJDK-2123: Algorithms lockdown @@ -1390,8 +1395,10 @@ Patch1001: fips-%{featurever}u-%{fipsver}.patch # ############################################# -# JDK-8375294: (fs) Files.copy can fail with EOPNOTSUPP when copy_file_range not supported -Patch2001: jdk8375294-handle-EOPNOTSUPP-in-copying.patch +# JDK-8347901: C2 should remove unused leaf / pure runtime calls +Patch2002: jdk8347901-c2_unused_leaf_removal.patch +# JDK-83787313: C2: performance regression due to missing constant folding for Math.pow() +Patch2003: jdk8378713-c2_missing_pow_constant_folding.patch ############################################# # @@ -1456,8 +1463,8 @@ BuildRequires: %{pkgnameroot}-misc = %{epoch}:%{version}-%{prelease}.%{portables %ifarch %{zero_arches} BuildRequires: libffi-devel %endif -# 2026a required as of JDK-8379035 -BuildRequires: tzdata-java >= 2026a +# 2026b required as of JDK-8383175 +BuildRequires: tzdata-java >= 2026b # Earlier versions have a bug in tree vectorization on PPC BuildRequires: gcc >= 4.8.3-8 @@ -1480,17 +1487,17 @@ BuildRequires: libpng-devel BuildRequires: zlib-devel %else # Version in src/java.desktop/share/legal/freetype.md -Provides: bundled(freetype) = 2.14.2 +Provides: bundled(freetype) = 2.14.3 # Version in src/java.desktop/share/native/libsplashscreen/giflib/gif_lib.h -Provides: bundled(giflib) = 6.1.2 +Provides: bundled(giflib) = 6.1.3 # Version in src/java.desktop/share/native/libharfbuzz/hb-version.h -Provides: bundled(harfbuzz) = 12.3.2 +Provides: bundled(harfbuzz) = 14.2.0 # Version in src/java.desktop/share/native/liblcms/lcms2.h -Provides: bundled(lcms2) = 2.17.0 +Provides: bundled(lcms2) = 2.19.1 # Version in src/java.desktop/share/native/libjavajpeg/jpeglib.h Provides: bundled(libjpeg) = 6b # Version in src/java.desktop/share/native/libsplashscreen/libpng/png.h -Provides: bundled(libpng) = 1.6.57 +Provides: bundled(libpng) = 1.6.58 # Version in src/java.base/share/native/libzip/zlib/zlib.h Provides: bundled(zlib) = 1.3.2 %endif @@ -1910,24 +1917,13 @@ sh %{SOURCE12} %{top_level_dir_name} %endif # Patch the JDK -# This syntax is deprecated: -# %patchN [...] -# and should be replaced with: -# %patch -PN [...] -# For example: -# %patch1001 -p1 -# becomes: -# %patch -P1001 -p1 -# The replacement format suggested by recent (circa Fedora 38) RPM -# deprecation messages: -# %patch N [...] -# is not backward-compatible with prior (circa RHEL-8) versions of -# rpmbuild. + pushd %{top_level_dir_name} # Add crypto policy and FIPS support %patch -P1001 -p1 -# Add EOPNOTSUPP patch -%patch -P2001 -p1 +# Add C2 patches +%patch -P2002 -p1 +%patch -P2003 -p1 popd # openjdk # Patch NSS adapter @@ -2104,10 +2100,7 @@ $JAVA_HOME/bin/java -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -versi # Check translations are available for new timezones (during flatpak builds, the # tzdb.dat used by this test is not where the test expects it, so this is # disabled for flatpak builds) - # Disable test until we are on the latest JDK - $JAVA_HOME/bin/javac -d . %{SOURCE18} - $JAVA_HOME/bin/java $(echo $(basename %{SOURCE18})|sed "s|\.java||") JRE - $JAVA_HOME/bin/java -Djava.locale.providers=CLDR $(echo $(basename %{SOURCE18})|sed "s|\.java||") CLDR + $JAVA_HOME/bin/java %{SOURCE18} %endif # Check src.zip has all sources. See RHBZ#1130490 @@ -2602,6 +2595,46 @@ exit 0 %endif %changelog +* Thu Jul 16 2026 Andrew Hughes - 1:25.0.4.0.7-1.0 +- Update to jdk-25.0.4+7 (GA) +- Update release notes to 25.0.4+7 +- Bump freetype version to 2.14.3 following JDK-8385390 +- Bump giflib version to 6.1.3 following JDK-8384902 +- Bump HarfBuzz version to 14.2.0 following JDK-8385490 +- Bump lcms2 version to 2.19.1 following JDK-8375065 & JDK-8383354 +- Bump libpng version to 1.6.58 following JDK-8384495 +- Require tzdata 2026b due to upstream inclusion of JDK-8383175 +- Drop local copy of JDK-8375294 EOPNOTSUPP patch +- Obsolete old RHEL releases (9.7.0-z, 10.1-z) +- Revert fr_FR and de_DE changes made in d43f0e6186370fdeb0ca2f3594f39783e20eef1c now JDK-8382020 is fixed +- Simplify TestTranslations run now there is only the CLDR provider and one set of data (JDK-8174269) +- Make zone string debug output optional in TestTranslations +- Sync the copy of the portable specfile with the latest update +- ** This tarball is embargoed until 2026-07-21 @ 1pm PT. ** +- Resolves: RHEL-188883 +- Resolves: RHEL-212294 +- Resolves: RHEL-212296 + +* Tue Jul 14 2026 Andrew Hughes - 1:25.0.3.0.9-3.1 +- Cleanup tagging and gating scripts to appease shellcheck: +- * scripts/builds/build_vanilla.sh: Use an array to handle the varying arguments to rhpkg. +- * scripts/builds/check_signatures.sh: Quote variable usage. +- * scripts/builds/waive_issue.sh: Remove redundant 'test "x"' usage. +- * scripts/builds/waive_leapp_issue.sh: Likewise. +- * scripts/builds/waive_rpminspect.sh: Likewise. +- * scripts/builds/waive_usual_rpminspect.sh: Likewise and add missing WORKING_DIR variable. +- * scripts/builds/waive_usual_tier0.sh: Remove redundant 'test "x"' usage. +- Remove macro references in comments where possible (%dnl not compatible enough yet) +- Move version information and core NVR definitions back towards the top of the file +- Specify portablerelease and rpmrelease (always 0 for portables) in the Release field +- Add 25u backports of JDK-8347901 & JDK-8378713 C2 performance fixes +- Sync the copy of the portable specfile with the latest update +- Related: RHEL-155327 +- Related: RHEL-155339 +- Resolves: RHEL-150977 +- Resolves: RHEL-210972 +- Resolves: RHEL-210993 + * Sat Apr 18 2026 Andrew Hughes - 1:25.0.3.0.9-1 - Update to jdk-25.0.3+9 (GA) - Update release notes to 25.0.3+9 diff --git a/jdk8347901-c2_unused_leaf_removal.patch b/jdk8347901-c2_unused_leaf_removal.patch new file mode 100644 index 0000000..bae136b --- /dev/null +++ b/jdk8347901-c2_unused_leaf_removal.patch @@ -0,0 +1,772 @@ +From 09853461a6896ab1f15469c753c21ca212e7e650 Mon Sep 17 00:00:00 2001 +From: duke +Date: Tue, 7 Apr 2026 15:14:53 +0000 +Subject: [PATCH 1/2] Backport ed70910b0f3e1b19d915ec13ac3434407d01bc5d + +--- + src/hotspot/share/opto/callnode.cpp | 53 +++++++- + src/hotspot/share/opto/callnode.hpp | 29 ++++- + src/hotspot/share/opto/classes.hpp | 2 + + src/hotspot/share/opto/compile.cpp | 19 +++ + src/hotspot/share/opto/divnode.cpp | 158 ++++++++++-------------- + src/hotspot/share/opto/divnode.hpp | 35 +++--- + src/hotspot/share/opto/graphKit.cpp | 29 +++-- + src/hotspot/share/opto/graphKit.hpp | 1 + + src/hotspot/share/opto/library_call.cpp | 2 +- + src/hotspot/share/opto/macro.cpp | 15 +-- + src/hotspot/share/opto/multnode.cpp | 13 ++ + src/hotspot/share/opto/multnode.hpp | 46 +++++++ + src/hotspot/share/opto/node.cpp | 12 +- + src/hotspot/share/opto/node.hpp | 5 +- + src/hotspot/share/opto/parse2.cpp | 8 +- + 15 files changed, 282 insertions(+), 145 deletions(-) + +diff --git a/src/hotspot/share/opto/callnode.cpp b/src/hotspot/share/opto/callnode.cpp +index 6f13ce0f809..fc4b0c35dff 100644 +--- a/src/hotspot/share/opto/callnode.cpp ++++ b/src/hotspot/share/opto/callnode.cpp +@@ -935,7 +935,7 @@ Node *CallNode::result_cast() { + } + + +-void CallNode::extract_projections(CallProjections* projs, bool separate_io_proj, bool do_asserts) { ++void CallNode::extract_projections(CallProjections* projs, bool separate_io_proj, bool do_asserts) const { + projs->fallthrough_proj = nullptr; + projs->fallthrough_catchproj = nullptr; + projs->fallthrough_ioproj = nullptr; +@@ -1319,6 +1319,57 @@ void CallLeafVectorNode::calling_convention( BasicType* sig_bt, VMRegPair *parm_ + + + //============================================================================= ++bool CallLeafPureNode::is_unused() const { ++ return proj_out_or_null(TypeFunc::Parms) == nullptr; ++} ++ ++bool CallLeafPureNode::is_dead() const { ++ return proj_out_or_null(TypeFunc::Control) == nullptr; ++} ++ ++/* We make a tuple of the global input state + TOP for the output values. ++ * We use this to delete a pure function that is not used: by replacing the call with ++ * such a tuple, we let output Proj's idealization pick the corresponding input of the ++ * pure call, so jumping over it, and effectively, removing the call from the graph. ++ * This avoids doing the graph surgery manually, but leaves that to IGVN ++ * that is specialized for doing that right. We need also tuple components for output ++ * values of the function to respect the return arity, and in case there is a projection ++ * that would pick an output (which shouldn't happen at the moment). ++ */ ++TupleNode* CallLeafPureNode::make_tuple_of_input_state_and_top_return_values(const Compile* C) const { ++ // Transparently propagate input state but parameters ++ TupleNode* tuple = TupleNode::make( ++ tf()->range(), ++ in(TypeFunc::Control), ++ in(TypeFunc::I_O), ++ in(TypeFunc::Memory), ++ in(TypeFunc::FramePtr), ++ in(TypeFunc::ReturnAdr)); ++ ++ // And add TOPs for the return values ++ for (uint i = TypeFunc::Parms; i < tf()->range()->cnt(); i++) { ++ tuple->set_req(i, C->top()); ++ } ++ ++ return tuple; ++} ++ ++Node* CallLeafPureNode::Ideal(PhaseGVN* phase, bool can_reshape) { ++ if (is_dead()) { ++ return nullptr; ++ } ++ ++ // We need to wait until IGVN because during parsing, usages might still be missing ++ // and we would remove the call immediately. ++ if (can_reshape && is_unused()) { ++ // The result is not used. We remove the call by replacing it with a tuple, that ++ // is later disintegrated by the projections. ++ return make_tuple_of_input_state_and_top_return_values(phase->C); ++ } ++ ++ return CallRuntimeNode::Ideal(phase, can_reshape); ++} ++ + #ifndef PRODUCT + void CallLeafNode::dump_spec(outputStream *st) const { + st->print("# "); +diff --git a/src/hotspot/share/opto/callnode.hpp b/src/hotspot/share/opto/callnode.hpp +index 213fbda4e89..2462a88143f 100644 +--- a/src/hotspot/share/opto/callnode.hpp ++++ b/src/hotspot/share/opto/callnode.hpp +@@ -752,7 +752,7 @@ class CallNode : public SafePointNode { + // Collect all the interesting edges from a call for use in + // replacing the call by something else. Used by macro expansion + // and the late inlining support. +- void extract_projections(CallProjections* projs, bool separate_io_proj, bool do_asserts = true); ++ void extract_projections(CallProjections* projs, bool separate_io_proj, bool do_asserts = true) const; + + virtual uint match_edge(uint idx) const; + +@@ -928,6 +928,33 @@ class CallLeafNode : public CallRuntimeNode { + #endif + }; + ++/* A pure function call, they are assumed not to be safepoints, not to read or write memory, ++ * have no exception... They just take parameters, return a value without side effect. It is ++ * always correct to create some, or remove them, if the result is not used. ++ * ++ * They still have control input to allow easy lowering into other kind of calls that require ++ * a control, but this is more a technical than a moral constraint. ++ * ++ * Pure calls must have only control and data input and output: I/O, Memory and so on must be top. ++ * Nevertheless, pure calls can typically be expensive math operations so care must be taken ++ * when letting the node float. ++ */ ++class CallLeafPureNode : public CallLeafNode { ++protected: ++ bool is_unused() const; ++ bool is_dead() const; ++ TupleNode* make_tuple_of_input_state_and_top_return_values(const Compile* C) const; ++ ++public: ++ CallLeafPureNode(const TypeFunc* tf, address addr, const char* name, ++ const TypePtr* adr_type) ++ : CallLeafNode(tf, addr, name, adr_type) { ++ init_class_id(Class_CallLeafPure); ++ } ++ int Opcode() const override; ++ Node* Ideal(PhaseGVN* phase, bool can_reshape) override; ++}; ++ + //------------------------------CallLeafNoFPNode------------------------------- + // CallLeafNode, not using floating point or using it in the same manner as + // the generated code +diff --git a/src/hotspot/share/opto/classes.hpp b/src/hotspot/share/opto/classes.hpp +index bc259eed2d1..587d5fad8f2 100644 +--- a/src/hotspot/share/opto/classes.hpp ++++ b/src/hotspot/share/opto/classes.hpp +@@ -61,6 +61,7 @@ macro(CallDynamicJava) + macro(CallJava) + macro(CallLeaf) + macro(CallLeafNoFP) ++macro(CallLeafPure) + macro(CallLeafVector) + macro(CallRuntime) + macro(CallStaticJava) +@@ -372,6 +373,7 @@ macro(SubI) + macro(SubL) + macro(TailCall) + macro(TailJump) ++macro(Tuple) + macro(MacroLogicV) + macro(ThreadLocal) + macro(Unlock) +diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp +index 2b956dcb5d8..9f7f48b9a34 100644 +--- a/src/hotspot/share/opto/compile.cpp ++++ b/src/hotspot/share/opto/compile.cpp +@@ -3298,6 +3298,25 @@ void Compile::final_graph_reshaping_main_switch(Node* n, Final_Reshape_Counts& f + case Op_Opaque1: // Remove Opaque Nodes before matching + n->subsume_by(n->in(1), this); + break; ++ case Op_CallLeafPure: { ++ // If the pure call is not supported, then lower to a CallLeaf. ++ if (!Matcher::match_rule_supported(Op_CallLeafPure)) { ++ CallNode* call = n->as_Call(); ++ CallNode* new_call = new CallLeafNode(call->tf(), call->entry_point(), ++ call->_name, TypeRawPtr::BOTTOM); ++ new_call->init_req(TypeFunc::Control, call->in(TypeFunc::Control)); ++ new_call->init_req(TypeFunc::I_O, C->top()); ++ new_call->init_req(TypeFunc::Memory, C->top()); ++ new_call->init_req(TypeFunc::ReturnAdr, C->top()); ++ new_call->init_req(TypeFunc::FramePtr, C->top()); ++ for (unsigned int i = TypeFunc::Parms; i < call->tf()->domain()->cnt(); i++) { ++ new_call->init_req(i, call->in(i)); ++ } ++ n->subsume_by(new_call, this); ++ } ++ frc.inc_call_count(); ++ break; ++ } + case Op_CallStaticJava: + case Op_CallJava: + case Op_CallDynamicJava: +diff --git a/src/hotspot/share/opto/divnode.cpp b/src/hotspot/share/opto/divnode.cpp +index a70194274a7..5dd8be877ff 100644 +--- a/src/hotspot/share/opto/divnode.cpp ++++ b/src/hotspot/share/opto/divnode.cpp +@@ -42,19 +42,19 @@ + + #include + +-ModFloatingNode::ModFloatingNode(Compile* C, const TypeFunc* tf, const char* name) : CallLeafNode(tf, nullptr, name, TypeRawPtr::BOTTOM) { ++ModFloatingNode::ModFloatingNode(Compile* C, const TypeFunc* tf, address addr, const char* name) : CallLeafPureNode(tf, addr, name, TypeRawPtr::BOTTOM) { + add_flag(Flag_is_macro); + C->add_macro_node(this); + } + +-ModDNode::ModDNode(Compile* C, Node* a, Node* b) : ModFloatingNode(C, OptoRuntime::Math_DD_D_Type(), "drem") { ++ModDNode::ModDNode(Compile* C, Node* a, Node* b) : ModFloatingNode(C, OptoRuntime::Math_DD_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::drem), "drem") { + init_req(TypeFunc::Parms + 0, a); + init_req(TypeFunc::Parms + 1, C->top()); + init_req(TypeFunc::Parms + 2, b); + init_req(TypeFunc::Parms + 3, C->top()); + } + +-ModFNode::ModFNode(Compile* C, Node* a, Node* b) : ModFloatingNode(C, OptoRuntime::modf_Type(), "frem") { ++ModFNode::ModFNode(Compile* C, Node* a, Node* b) : ModFloatingNode(C, OptoRuntime::modf_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::frem), "frem") { + init_req(TypeFunc::Parms + 0, a); + init_req(TypeFunc::Parms + 1, b); + } +@@ -1516,137 +1516,109 @@ const Type* UModLNode::Value(PhaseGVN* phase) const { + return unsigned_mod_value(phase, this); + } + +-Node* ModFNode::Ideal(PhaseGVN* phase, bool can_reshape) { +- if (!can_reshape) { +- return nullptr; +- } +- PhaseIterGVN* igvn = phase->is_IterGVN(); +- +- bool result_is_unused = proj_out_or_null(TypeFunc::Parms) == nullptr; +- bool not_dead = proj_out_or_null(TypeFunc::Control) != nullptr; +- if (result_is_unused && not_dead) { +- return replace_with_con(igvn, TypeF::make(0.)); +- } +- +- // Either input is TOP ==> the result is TOP +- const Type* t1 = phase->type(dividend()); +- const Type* t2 = phase->type(divisor()); +- if (t1 == Type::TOP || t2 == Type::TOP) { +- return phase->C->top(); +- } +- ++const Type* ModFNode::get_result_if_constant(const Type* dividend, const Type* divisor) const { + // If either number is not a constant, we know nothing. +- if ((t1->base() != Type::FloatCon) || (t2->base() != Type::FloatCon)) { ++ if ((dividend->base() != Type::FloatCon) || (divisor->base() != Type::FloatCon)) { + return nullptr; // note: x%x can be either NaN or 0 + } + +- float f1 = t1->getf(); +- float f2 = t2->getf(); +- jint x1 = jint_cast(f1); // note: *(int*)&f1, not just (int)f1 +- jint x2 = jint_cast(f2); ++ float dividend_f = dividend->getf(); ++ float divisor_f = divisor->getf(); ++ jint dividend_i = jint_cast(dividend_f); // note: *(int*)&f1, not just (int)f1 ++ jint divisor_i = jint_cast(divisor_f); + + // If either is a NaN, return an input NaN +- if (g_isnan(f1)) { +- return replace_with_con(igvn, t1); ++ if (g_isnan(dividend_f)) { ++ return dividend; + } +- if (g_isnan(f2)) { +- return replace_with_con(igvn, t2); ++ if (g_isnan(divisor_f)) { ++ return divisor; + } + + // If an operand is infinity or the divisor is +/- zero, punt. +- if (!g_isfinite(f1) || !g_isfinite(f2) || x2 == 0 || x2 == min_jint) { ++ if (!g_isfinite(dividend_f) || !g_isfinite(divisor_f) || divisor_i == 0 || divisor_i == min_jint) { + return nullptr; + } + + // We must be modulo'ing 2 float constants. + // Make sure that the sign of the fmod is equal to the sign of the dividend +- jint xr = jint_cast(fmod(f1, f2)); +- if ((x1 ^ xr) < 0) { ++ jint xr = jint_cast(fmod(dividend_f, divisor_f)); ++ if ((dividend_i ^ xr) < 0) { + xr ^= min_jint; + } + +- return replace_with_con(igvn, TypeF::make(jfloat_cast(xr))); ++ return TypeF::make(jfloat_cast(xr)); + } + +-Node* ModDNode::Ideal(PhaseGVN* phase, bool can_reshape) { +- if (!can_reshape) { +- return nullptr; +- } +- PhaseIterGVN* igvn = phase->is_IterGVN(); +- +- bool result_is_unused = proj_out_or_null(TypeFunc::Parms) == nullptr; +- bool not_dead = proj_out_or_null(TypeFunc::Control) != nullptr; +- if (result_is_unused && not_dead) { +- return replace_with_con(igvn, TypeD::make(0.)); +- } +- +- // Either input is TOP ==> the result is TOP +- const Type* t1 = phase->type(dividend()); +- const Type* t2 = phase->type(divisor()); +- if (t1 == Type::TOP || t2 == Type::TOP) { +- return nullptr; +- } +- ++const Type* ModDNode::get_result_if_constant(const Type* dividend, const Type* divisor) const { + // If either number is not a constant, we know nothing. +- if ((t1->base() != Type::DoubleCon) || (t2->base() != Type::DoubleCon)) { ++ if ((dividend->base() != Type::DoubleCon) || (divisor->base() != Type::DoubleCon)) { + return nullptr; // note: x%x can be either NaN or 0 + } + +- double f1 = t1->getd(); +- double f2 = t2->getd(); +- jlong x1 = jlong_cast(f1); // note: *(long*)&f1, not just (long)f1 +- jlong x2 = jlong_cast(f2); ++ double dividend_d = dividend->getd(); ++ double divisor_d = divisor->getd(); ++ jlong dividend_l = jlong_cast(dividend_d); // note: *(long*)&f1, not just (long)f1 ++ jlong divisor_l = jlong_cast(divisor_d); + + // If either is a NaN, return an input NaN +- if (g_isnan(f1)) { +- return replace_with_con(igvn, t1); ++ if (g_isnan(dividend_d)) { ++ return dividend; + } +- if (g_isnan(f2)) { +- return replace_with_con(igvn, t2); ++ if (g_isnan(divisor_d)) { ++ return divisor; + } + + // If an operand is infinity or the divisor is +/- zero, punt. +- if (!g_isfinite(f1) || !g_isfinite(f2) || x2 == 0 || x2 == min_jlong) { ++ if (!g_isfinite(dividend_d) || !g_isfinite(divisor_d) || divisor_l == 0 || divisor_l == min_jlong) { + return nullptr; + } + + // We must be modulo'ing 2 double constants. + // Make sure that the sign of the fmod is equal to the sign of the dividend +- jlong xr = jlong_cast(fmod(f1, f2)); +- if ((x1 ^ xr) < 0) { ++ jlong xr = jlong_cast(fmod(dividend_d, divisor_d)); ++ if ((dividend_l ^ xr) < 0) { + xr ^= min_jlong; + } + +- return replace_with_con(igvn, TypeD::make(jdouble_cast(xr))); ++ return TypeD::make(jdouble_cast(xr)); + } + +-Node* ModFloatingNode::replace_with_con(PhaseIterGVN* phase, const Type* con) { +- Compile* C = phase->C; +- Node* con_node = phase->makecon(con); +- CallProjections projs; +- extract_projections(&projs, false, false); +- phase->replace_node(projs.fallthrough_proj, in(TypeFunc::Control)); +- if (projs.fallthrough_catchproj != nullptr) { +- phase->replace_node(projs.fallthrough_catchproj, in(TypeFunc::Control)); +- } +- if (projs.fallthrough_memproj != nullptr) { +- phase->replace_node(projs.fallthrough_memproj, in(TypeFunc::Memory)); +- } +- if (projs.catchall_memproj != nullptr) { +- phase->replace_node(projs.catchall_memproj, C->top()); +- } +- if (projs.fallthrough_ioproj != nullptr) { +- phase->replace_node(projs.fallthrough_ioproj, in(TypeFunc::I_O)); +- } +- assert(projs.catchall_ioproj == nullptr, "no exceptions from floating mod"); +- assert(projs.catchall_catchproj == nullptr, "no exceptions from floating mod"); +- if (projs.resproj != nullptr) { +- phase->replace_node(projs.resproj, con_node); ++Node* ModFloatingNode::Ideal(PhaseGVN* phase, bool can_reshape) { ++ if (can_reshape) { ++ PhaseIterGVN* igvn = phase->is_IterGVN(); ++ ++ // Either input is TOP ==> the result is TOP ++ const Type* dividend_type = phase->type(dividend()); ++ const Type* divisor_type = phase->type(divisor()); ++ if (dividend_type == Type::TOP || divisor_type == Type::TOP) { ++ return phase->C->top(); ++ } ++ const Type* constant_result = get_result_if_constant(dividend_type, divisor_type); ++ if (constant_result != nullptr) { ++ return make_tuple_of_input_state_and_constant_result(igvn, constant_result); ++ } + } +- phase->replace_node(this, C->top()); +- C->remove_macro_node(this); +- disconnect_inputs(C); +- return nullptr; ++ ++ return CallLeafPureNode::Ideal(phase, can_reshape); ++} ++ ++/* Give a tuple node for ::Ideal to return, made of the input state (control to return addr) ++ * and the given constant result. Idealization of projections will make sure to transparently ++ * propagate the input state and replace the result by the said constant. ++ */ ++TupleNode* ModFloatingNode::make_tuple_of_input_state_and_constant_result(PhaseIterGVN* phase, const Type* con) const { ++ Node* con_node = phase->makecon(con); ++ TupleNode* tuple = TupleNode::make( ++ tf()->range(), ++ in(TypeFunc::Control), ++ in(TypeFunc::I_O), ++ in(TypeFunc::Memory), ++ in(TypeFunc::FramePtr), ++ in(TypeFunc::ReturnAdr), ++ con_node); ++ ++ return tuple; + } + + //============================================================================= +diff --git a/src/hotspot/share/opto/divnode.hpp b/src/hotspot/share/opto/divnode.hpp +index 127e2431b0b..b13460c89f5 100644 +--- a/src/hotspot/share/opto/divnode.hpp ++++ b/src/hotspot/share/opto/divnode.hpp +@@ -156,40 +156,45 @@ class ModLNode : public Node { + }; + + // Base class for float and double modulus +-class ModFloatingNode : public CallLeafNode { ++class ModFloatingNode : public CallLeafPureNode { ++ TupleNode* make_tuple_of_input_state_and_constant_result(PhaseIterGVN* phase, const Type* con) const; ++ + protected: +- Node* replace_with_con(PhaseIterGVN* phase, const Type* con); ++ virtual Node* dividend() const = 0; ++ virtual Node* divisor() const = 0; ++ virtual const Type* get_result_if_constant(const Type* dividend, const Type* divisor) const = 0; + + public: +- ModFloatingNode(Compile* C, const TypeFunc* tf, const char *name); ++ ModFloatingNode(Compile* C, const TypeFunc* tf, address addr, const char* name); ++ Node* Ideal(PhaseGVN* phase, bool can_reshape) override; + }; + + // Float Modulus + class ModFNode : public ModFloatingNode { + private: +- Node* dividend() const { return in(TypeFunc::Parms + 0); } +- Node* divisor() const { return in(TypeFunc::Parms + 1); } ++ Node* dividend() const override { return in(TypeFunc::Parms + 0); } ++ Node* divisor() const override { return in(TypeFunc::Parms + 1); } ++ const Type* get_result_if_constant(const Type* dividend, const Type* divisor) const override; + + public: + ModFNode(Compile* C, Node* a, Node* b); +- virtual int Opcode() const; +- virtual uint ideal_reg() const { return Op_RegF; } +- virtual uint size_of() const { return sizeof(*this); } +- virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); ++ int Opcode() const override; ++ uint ideal_reg() const override { return Op_RegF; } ++ uint size_of() const override { return sizeof(*this); } + }; + + // Double Modulus + class ModDNode : public ModFloatingNode { + private: +- Node* dividend() const { return in(TypeFunc::Parms + 0); } +- Node* divisor() const { return in(TypeFunc::Parms + 2); } ++ Node* dividend() const override { return in(TypeFunc::Parms + 0); } ++ Node* divisor() const override { return in(TypeFunc::Parms + 2); } ++ const Type* get_result_if_constant(const Type* dividend, const Type* divisor) const override; + + public: + ModDNode(Compile* C, Node* a, Node* b); +- virtual int Opcode() const; +- virtual uint ideal_reg() const { return Op_RegD; } +- virtual uint size_of() const { return sizeof(*this); } +- virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); ++ int Opcode() const override; ++ uint ideal_reg() const override { return Op_RegD; } ++ uint size_of() const override { return sizeof(*this); } + }; + + //------------------------------UModINode--------------------------------------- +diff --git a/src/hotspot/share/opto/graphKit.cpp b/src/hotspot/share/opto/graphKit.cpp +index 20feca26ede..1b8b7008578 100644 +--- a/src/hotspot/share/opto/graphKit.cpp ++++ b/src/hotspot/share/opto/graphKit.cpp +@@ -1880,14 +1880,20 @@ Node* GraphKit::set_results_for_java_call(CallJavaNode* call, bool separate_io_p + // after the call, if this call has restricted memory effects. + Node* GraphKit::set_predefined_input_for_runtime_call(SafePointNode* call, Node* narrow_mem) { + // Set fixed predefined input arguments +- Node* memory = reset_memory(); +- Node* m = narrow_mem == nullptr ? memory : narrow_mem; +- call->init_req( TypeFunc::Control, control() ); +- call->init_req( TypeFunc::I_O, top() ); // does no i/o +- call->init_req( TypeFunc::Memory, m ); // may gc ptrs +- call->init_req( TypeFunc::FramePtr, frameptr() ); +- call->init_req( TypeFunc::ReturnAdr, top() ); +- return memory; ++ call->init_req(TypeFunc::Control, control()); ++ call->init_req(TypeFunc::I_O, top()); // does no i/o ++ call->init_req(TypeFunc::ReturnAdr, top()); ++ if (call->is_CallLeafPure()) { ++ call->init_req(TypeFunc::Memory, top()); ++ call->init_req(TypeFunc::FramePtr, top()); ++ return nullptr; ++ } else { ++ Node* memory = reset_memory(); ++ Node* m = narrow_mem == nullptr ? memory : narrow_mem; ++ call->init_req(TypeFunc::Memory, m); // may gc ptrs ++ call->init_req(TypeFunc::FramePtr, frameptr()); ++ return memory; ++ } + } + + //-------------------set_predefined_output_for_runtime_call-------------------- +@@ -1905,6 +1911,11 @@ void GraphKit::set_predefined_output_for_runtime_call(Node* call, + const TypePtr* hook_mem) { + // no i/o + set_control(_gvn.transform( new ProjNode(call,TypeFunc::Control) )); ++ if (call->is_CallLeafPure()) { ++ // Pure function have only control (for now) and data output, in particular ++ // they don't touch the memory, so we don't want a memory proj that is set after. ++ return; ++ } + if (keep_mem) { + // First clone the existing memory state + set_all_memory(keep_mem); +@@ -2491,6 +2502,8 @@ Node* GraphKit::make_runtime_call(int flags, + } else if (flags & RC_VECTOR){ + uint num_bits = call_type->range()->field_at(TypeFunc::Parms)->is_vect()->length_in_bytes() * BitsPerByte; + call = new CallLeafVectorNode(call_type, call_addr, call_name, adr_type, num_bits); ++ } else if (flags & RC_PURE) { ++ call = new CallLeafPureNode(call_type, call_addr, call_name, adr_type); + } else { + call = new CallLeafNode(call_type, call_addr, call_name, adr_type); + } +diff --git a/src/hotspot/share/opto/graphKit.hpp b/src/hotspot/share/opto/graphKit.hpp +index 28773d75333..806a211d7e2 100644 +--- a/src/hotspot/share/opto/graphKit.hpp ++++ b/src/hotspot/share/opto/graphKit.hpp +@@ -784,6 +784,7 @@ class GraphKit : public Phase { + RC_NARROW_MEM = 16, // input memory is same as output + RC_UNCOMMON = 32, // freq. expected to be like uncommon trap + RC_VECTOR = 64, // CallLeafVectorNode ++ RC_PURE = 128, // CallLeaf is pure + RC_LEAF = 0 // null value: no flags set + }; + +diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp +index f74af38387c..12960d101a8 100644 +--- a/src/hotspot/share/opto/library_call.cpp ++++ b/src/hotspot/share/opto/library_call.cpp +@@ -1802,7 +1802,7 @@ bool LibraryCallKit::runtime_math(const TypeFunc* call_type, address funcAddr, c + Node* b = (call_type == OptoRuntime::Math_DD_D_Type()) ? argument(2) : nullptr; + + const TypePtr* no_memory_effects = nullptr; +- Node* trig = make_runtime_call(RC_LEAF, call_type, funcAddr, funcName, ++ Node* trig = make_runtime_call(RC_LEAF | RC_PURE, call_type, funcAddr, funcName, + no_memory_effects, + a, top(), b, b ? top() : nullptr); + Node* value = _gvn.transform(new ProjNode(trig, TypeFunc::Parms+0)); +diff --git a/src/hotspot/share/opto/macro.cpp b/src/hotspot/share/opto/macro.cpp +index acf1dbabf19..aafc5d3c170 100644 +--- a/src/hotspot/share/opto/macro.cpp ++++ b/src/hotspot/share/opto/macro.cpp +@@ -2638,17 +2638,14 @@ bool PhaseMacroExpand::expand_macro_nodes() { + switch (n->Opcode()) { + case Op_ModD: + case Op_ModF: { +- bool is_drem = n->Opcode() == Op_ModD; + CallNode* mod_macro = n->as_Call(); +- CallNode* call = new CallLeafNode(mod_macro->tf(), +- is_drem ? CAST_FROM_FN_PTR(address, SharedRuntime::drem) +- : CAST_FROM_FN_PTR(address, SharedRuntime::frem), +- is_drem ? "drem" : "frem", TypeRawPtr::BOTTOM); ++ CallNode* call = new CallLeafPureNode(mod_macro->tf(), mod_macro->entry_point(), ++ mod_macro->_name, TypeRawPtr::BOTTOM); + call->init_req(TypeFunc::Control, mod_macro->in(TypeFunc::Control)); +- call->init_req(TypeFunc::I_O, mod_macro->in(TypeFunc::I_O)); +- call->init_req(TypeFunc::Memory, mod_macro->in(TypeFunc::Memory)); +- call->init_req(TypeFunc::ReturnAdr, mod_macro->in(TypeFunc::ReturnAdr)); +- call->init_req(TypeFunc::FramePtr, mod_macro->in(TypeFunc::FramePtr)); ++ call->init_req(TypeFunc::I_O, C->top()); ++ call->init_req(TypeFunc::Memory, C->top()); ++ call->init_req(TypeFunc::ReturnAdr, C->top()); ++ call->init_req(TypeFunc::FramePtr, C->top()); + for (unsigned int i = 0; i < mod_macro->tf()->domain()->cnt() - TypeFunc::Parms; i++) { + call->init_req(TypeFunc::Parms + i, mod_macro->in(TypeFunc::Parms + i)); + } +diff --git a/src/hotspot/share/opto/multnode.cpp b/src/hotspot/share/opto/multnode.cpp +index 736e84315ee..f429d5daac0 100644 +--- a/src/hotspot/share/opto/multnode.cpp ++++ b/src/hotspot/share/opto/multnode.cpp +@@ -120,6 +120,10 @@ const TypePtr *ProjNode::adr_type() const { + if (bottom_type() == Type::MEMORY) { + // in(0) might be a narrow MemBar; otherwise we will report TypePtr::BOTTOM + Node* ctrl = in(0); ++ if (ctrl->Opcode() == Op_Tuple) { ++ // Jumping over Tuples: the i-th projection of a Tuple is the i-th input of the Tuple. ++ ctrl = ctrl->in(_con); ++ } + if (ctrl == nullptr) return nullptr; // node is dead + const TypePtr* adr_type = ctrl->adr_type(); + #ifdef ASSERT +@@ -163,6 +167,15 @@ void ProjNode::check_con() const { + assert(_con < t->is_tuple()->cnt(), "ProjNode::_con must be in range"); + } + ++//------------------------------Identity--------------------------------------- ++Node* ProjNode::Identity(PhaseGVN* phase) { ++ if (in(0) != nullptr && in(0)->Opcode() == Op_Tuple) { ++ // Jumping over Tuples: the i-th projection of a Tuple is the i-th input of the Tuple. ++ return in(0)->in(_con); ++ } ++ return this; ++} ++ + //------------------------------Value------------------------------------------ + const Type* ProjNode::Value(PhaseGVN* phase) const { + if (in(0) == nullptr) return Type::TOP; +diff --git a/src/hotspot/share/opto/multnode.hpp b/src/hotspot/share/opto/multnode.hpp +index dff2caed38d..834dcfdca6d 100644 +--- a/src/hotspot/share/opto/multnode.hpp ++++ b/src/hotspot/share/opto/multnode.hpp +@@ -82,6 +82,7 @@ class ProjNode : public Node { + virtual const Type *bottom_type() const; + virtual const TypePtr *adr_type() const; + virtual bool pinned() const; ++ virtual Node* Identity(PhaseGVN* phase); + virtual const Type* Value(PhaseGVN* phase) const; + virtual uint ideal_reg() const; + virtual const RegMask &out_RegMask() const; +@@ -105,4 +106,49 @@ class ProjNode : public Node { + ProjNode* other_if_proj() const; + }; + ++/* Tuples are used to avoid manual graph surgery. When a node with Proj outputs (such as a call) ++ * must be removed and its ouputs replaced by its input, or some other value, we can make its ++ * ::Ideal return a tuple of what we want for each output: the ::Identity of output Proj will ++ * take care to jump over the Tuple and directly pick up the right input of the Tuple. ++ * ++ * For instance, if a function call is proven to have no side effect and return the constant 0, ++ * we can replace it with the 6-tuple: ++ * (control input, IO input, memory input, frame ptr input, return addr input, Con:0) ++ * all the output projections will pick up the input of the now gone call, except for the result ++ * projection that is replaced by 0. ++ * ++ * Using TupleNode avoid manual graph surgery and leave that to our expert surgeon: IGVN. ++ * Since the user of a Tuple are expected to be Proj, when creating a tuple during idealization, ++ * the output Proj should be enqueued for IGVN immediately after, and the tuple should not survive ++ * after the current IGVN. ++ */ ++class TupleNode : public MultiNode { ++ const TypeTuple* _tf; ++ ++ template ++ static void make_helper(TupleNode* tn, uint i, Node* node, NN... nn) { ++ tn->set_req(i, node); ++ make_helper(tn, i + 1, nn...); ++ } ++ ++ static void make_helper(TupleNode*, uint) {} ++ ++public: ++ TupleNode(const TypeTuple* tf) : MultiNode(tf->cnt()), _tf(tf) {} ++ ++ int Opcode() const override; ++ const Type* bottom_type() const override { return _tf; } ++ ++ /* Give as many `Node*` as you want in the `nn` pack: ++ * TupleNode::make(tf, input1) ++ * TupleNode::make(tf, input1, input2, input3, input4) ++ */ ++ template ++ static TupleNode* make(const TypeTuple* tf, NN... nn) { ++ TupleNode* tn = new TupleNode(tf); ++ make_helper(tn, 0, nn...); ++ return tn; ++ } ++}; ++ + #endif // SHARE_OPTO_MULTNODE_HPP +diff --git a/src/hotspot/share/opto/node.cpp b/src/hotspot/share/opto/node.cpp +index 8f6c67c16f5..5ecc038954d 100644 +--- a/src/hotspot/share/opto/node.cpp ++++ b/src/hotspot/share/opto/node.cpp +@@ -2946,23 +2946,13 @@ bool Node::is_dead_loop_safe() const { + bool Node::is_div_or_mod(BasicType bt) const { return Opcode() == Op_Div(bt) || Opcode() == Op_Mod(bt) || + Opcode() == Op_UDiv(bt) || Opcode() == Op_UMod(bt); } + +-bool Node::is_pure_function() const { +- switch (Opcode()) { +- case Op_ModD: +- case Op_ModF: +- return true; +- default: +- return false; +- } +-} +- + // `maybe_pure_function` is assumed to be the input of `this`. This is a bit redundant, + // but we already have and need maybe_pure_function in all the call sites, so + // it makes it obvious that the `maybe_pure_function` is the same node as in the caller, + // while it takes more thinking to realize that a locally computed in(0) must be equal to + // the local in the caller. + bool Node::is_data_proj_of_pure_function(const Node* maybe_pure_function) const { +- return Opcode() == Op_Proj && as_Proj()->_con == TypeFunc::Parms && maybe_pure_function->is_pure_function(); ++ return Opcode() == Op_Proj && as_Proj()->_con == TypeFunc::Parms && maybe_pure_function->is_CallLeafPure(); + } + + //============================================================================= +diff --git a/src/hotspot/share/opto/node.hpp b/src/hotspot/share/opto/node.hpp +index 2bbb10879f5..dc0ac474c4b 100644 +--- a/src/hotspot/share/opto/node.hpp ++++ b/src/hotspot/share/opto/node.hpp +@@ -54,6 +54,7 @@ class CallDynamicJavaNode; + class CallJavaNode; + class CallLeafNode; + class CallLeafNoFPNode; ++class CallLeafPureNode; + class CallNode; + class CallRuntimeNode; + class CallStaticJavaNode; +@@ -673,6 +674,7 @@ class Node { + DEFINE_CLASS_ID(CallRuntime, Call, 1) + DEFINE_CLASS_ID(CallLeaf, CallRuntime, 0) + DEFINE_CLASS_ID(CallLeafNoFP, CallLeaf, 0) ++ DEFINE_CLASS_ID(CallLeafPure, CallLeaf, 1) + DEFINE_CLASS_ID(Allocate, Call, 2) + DEFINE_CLASS_ID(AllocateArray, Allocate, 0) + DEFINE_CLASS_ID(AbstractLock, Call, 3) +@@ -907,6 +909,7 @@ class Node { + DEFINE_CLASS_QUERY(CallJava) + DEFINE_CLASS_QUERY(CallLeaf) + DEFINE_CLASS_QUERY(CallLeafNoFP) ++ DEFINE_CLASS_QUERY(CallLeafPure) + DEFINE_CLASS_QUERY(CallRuntime) + DEFINE_CLASS_QUERY(CallStaticJava) + DEFINE_CLASS_QUERY(Catch) +@@ -1289,8 +1292,6 @@ class Node { + + bool is_div_or_mod(BasicType bt) const; + +- bool is_pure_function() const; +- + bool is_data_proj_of_pure_function(const Node* maybe_pure_function) const; + + //----------------- Printing, etc +diff --git a/src/hotspot/share/opto/parse2.cpp b/src/hotspot/share/opto/parse2.cpp +index 1a4c3c91c4f..04b6e49b620 100644 +--- a/src/hotspot/share/opto/parse2.cpp ++++ b/src/hotspot/share/opto/parse2.cpp +@@ -1097,11 +1097,11 @@ void Parse::jump_switch_ranges(Node* key_val, SwitchRange *lo, SwitchRange *hi, + + Node* Parse::floating_point_mod(Node* a, Node* b, BasicType type) { + assert(type == BasicType::T_FLOAT || type == BasicType::T_DOUBLE, "only float and double are floating points"); +- CallNode* mod = type == BasicType::T_DOUBLE ? static_cast(new ModDNode(C, a, b)) : new ModFNode(C, a, b); ++ CallLeafPureNode* mod = type == BasicType::T_DOUBLE ? static_cast(new ModDNode(C, a, b)) : new ModFNode(C, a, b); + +- Node* prev_mem = set_predefined_input_for_runtime_call(mod); +- mod = _gvn.transform(mod)->as_Call(); +- set_predefined_output_for_runtime_call(mod, prev_mem, TypeRawPtr::BOTTOM); ++ set_predefined_input_for_runtime_call(mod); ++ mod = _gvn.transform(mod)->as_CallLeafPure(); ++ set_predefined_output_for_runtime_call(mod); + Node* result = _gvn.transform(new ProjNode(mod, TypeFunc::Parms + 0)); + record_for_igvn(mod); + return result; +-- +2.53.0 + diff --git a/jdk8375294-handle-EOPNOTSUPP-in-copying.patch b/jdk8375294-handle-EOPNOTSUPP-in-copying.patch deleted file mode 100644 index ea8076a..0000000 --- a/jdk8375294-handle-EOPNOTSUPP-in-copying.patch +++ /dev/null @@ -1,63 +0,0 @@ -From dbbdc1dffd10608195487fa139e77c4a90c80658 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Ji=C5=99=C3=AD=20Van=C4=9Bk?= -Date: Wed, 15 Apr 2026 12:54:49 +0000 -Subject: [PATCH] 8375294: (fs) Files.copy can fail with EOPNOTSUPP when - copy_file_range not supported - -Reviewed-by: andrew -Backport-of: 30cda00010888b6e9a2bf8cdeaedbb3eb4b6a222 ---- - src/java.base/linux/native/libnio/ch/FileDispatcherImpl.c | 5 +++-- - src/java.base/linux/native/libnio/fs/LinuxNativeDispatcher.c | 3 ++- - 2 files changed, 5 insertions(+), 3 deletions(-) - -diff --git a/src/java.base/linux/native/libnio/ch/FileDispatcherImpl.c b/src/java.base/linux/native/libnio/ch/FileDispatcherImpl.c -index efbd0ca5684..54d640b03a4 100644 ---- a/src/java.base/linux/native/libnio/ch/FileDispatcherImpl.c -+++ b/src/java.base/linux/native/libnio/ch/FileDispatcherImpl.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2000, 2024, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it -@@ -63,7 +63,7 @@ Java_sun_nio_ch_FileDispatcherImpl_transferFrom0(JNIEnv *env, jobject this, - if (n < 0) { - if (errno == EAGAIN) - return IOS_UNAVAILABLE; -- if (errno == ENOSYS) -+ if (errno == ENOSYS || errno == EOPNOTSUPP) - return IOS_UNSUPPORTED_CASE; - if ((errno == EBADF || errno == EINVAL || errno == EXDEV) && - ((ssize_t)count >= 0)) -@@ -103,6 +103,7 @@ Java_sun_nio_ch_FileDispatcherImpl_transferTo0(JNIEnv *env, jobject this, - case EINVAL: - case ENOSYS: - case EXDEV: -+ case EOPNOTSUPP: - // ignore and try sendfile() - break; - default: -diff --git a/src/java.base/linux/native/libnio/fs/LinuxNativeDispatcher.c b/src/java.base/linux/native/libnio/fs/LinuxNativeDispatcher.c -index c90e99dda07..4677411b0ba 100644 ---- a/src/java.base/linux/native/libnio/fs/LinuxNativeDispatcher.c -+++ b/src/java.base/linux/native/libnio/fs/LinuxNativeDispatcher.c -@@ -1,5 +1,5 @@ - /* -- * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. -+ * Copyright (c) 2008, 2026, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it -@@ -193,6 +193,7 @@ Java_sun_nio_fs_LinuxNativeDispatcher_directCopy0 - case EINVAL: - case ENOSYS: - case EXDEV: -+ case EOPNOTSUPP: - // ignore and try sendfile() - break; - default: --- -2.52.0 - diff --git a/jdk8378713-c2_missing_pow_constant_folding.patch b/jdk8378713-c2_missing_pow_constant_folding.patch new file mode 100644 index 0000000..6e6bb11 --- /dev/null +++ b/jdk8378713-c2_missing_pow_constant_folding.patch @@ -0,0 +1,626 @@ +From 1f61b6754b5abce07db45fd385a19c2cf9296a08 Mon Sep 17 00:00:00 2001 +From: Kangcheng Xu +Date: Mon, 27 Apr 2026 10:14:39 -0400 +Subject: [PATCH 2/2] Backport 7f631ea958e30246b927f3524f0fbf37334422b9 + +--- + src/hotspot/share/opto/callnode.cpp | 175 ++++++++++++++ + src/hotspot/share/opto/callnode.hpp | 17 ++ + src/hotspot/share/opto/classes.hpp | 1 + + src/hotspot/share/opto/library_call.cpp | 62 +---- + src/hotspot/share/opto/macro.cpp | 19 +- + .../intrinsics/math/PowDNodeTests.java | 218 ++++++++++++++++++ + .../compiler/lib/ir_framework/IRNode.java | 11 + + 7 files changed, 437 insertions(+), 66 deletions(-) + create mode 100644 test/hotspot/jtreg/compiler/intrinsics/math/PowDNodeTests.java + +diff --git a/src/hotspot/share/opto/callnode.cpp b/src/hotspot/share/opto/callnode.cpp +index fc4b0c35dff..cb6cc2082b3 100644 +--- a/src/hotspot/share/opto/callnode.cpp ++++ b/src/hotspot/share/opto/callnode.cpp +@@ -42,6 +42,7 @@ + #include "opto/rootnode.hpp" + #include "opto/runtime.hpp" + #include "runtime/sharedRuntime.hpp" ++#include "runtime/stubRoutines.hpp" + #include "utilities/powerOfTwo.hpp" + #include "code/vmreg.hpp" + +@@ -1354,6 +1355,25 @@ TupleNode* CallLeafPureNode::make_tuple_of_input_state_and_top_return_values(con + return tuple; + } + ++CallLeafPureNode* CallLeafPureNode::inline_call_leaf_pure_node(Node* control) const { ++ Node* top = Compile::current()->top(); ++ if (control == nullptr) { ++ control = in(TypeFunc::Control); ++ } ++ ++ CallLeafPureNode* call = new CallLeafPureNode(tf(), entry_point(), _name, nullptr); ++ call->init_req(TypeFunc::Control, control); ++ call->init_req(TypeFunc::I_O, top); ++ call->init_req(TypeFunc::Memory, top); ++ call->init_req(TypeFunc::ReturnAdr, top); ++ call->init_req(TypeFunc::FramePtr, top); ++ for (unsigned int i = 0; i < tf()->domain()->cnt() - TypeFunc::Parms; i++) { ++ call->init_req(TypeFunc::Parms + i, in(TypeFunc::Parms + i)); ++ } ++ ++ return call; ++} ++ + Node* CallLeafPureNode::Ideal(PhaseGVN* phase, bool can_reshape) { + if (is_dead()) { + return nullptr; +@@ -2424,3 +2444,158 @@ bool CallNode::may_modify_arraycopy_helper(const TypeOopPtr* dest_t, const TypeO + + return true; + } ++ ++PowDNode::PowDNode(Compile* C, Node* base, Node* exp) ++ : CallLeafPureNode( ++ OptoRuntime::Math_DD_D_Type(), ++ StubRoutines::dpow() != nullptr ? StubRoutines::dpow() : CAST_FROM_FN_PTR(address, SharedRuntime::dpow), ++ "pow", ++ nullptr) { ++ add_flag(Flag_is_macro); ++ C->add_macro_node(this); ++ ++ init_req(TypeFunc::Parms + 0, base); ++ init_req(TypeFunc::Parms + 1, C->top()); // double slot padding ++ init_req(TypeFunc::Parms + 2, exp); ++ init_req(TypeFunc::Parms + 3, C->top()); // double slot padding ++} ++ ++const Type* PowDNode::Value(PhaseGVN* phase) const { ++ const Type* t_base = phase->type(base()); ++ const Type* t_exp = phase->type(exp()); ++ ++ if (t_base == Type::TOP || t_exp == Type::TOP) { ++ return Type::TOP; ++ } ++ ++ const TypeD* base_con = t_base->isa_double_constant(); ++ const TypeD* exp_con = t_exp->isa_double_constant(); ++ const TypeD* result_t = nullptr; ++ ++ // constant folding: both inputs are constants ++ if (base_con != nullptr && exp_con != nullptr) { ++ result_t = TypeD::make(SharedRuntime::dpow(base_con->getd(), exp_con->getd())); ++ } ++ ++ // Special cases when only the exponent is known: ++ if (exp_con != nullptr) { ++ double e = exp_con->getd(); ++ ++ // If the second argument is positive or negative zero, then the result is 1.0. ++ // i.e., pow(x, +/-0.0D) => 1.0 ++ if (e == 0.0) { // true for both -0.0 and +0.0 ++ result_t = TypeD::ONE; ++ } ++ ++ // If the second argument is NaN, then the result is NaN. ++ // i.e., pow(x, NaN) => NaN ++ if (g_isnan(e)) { ++ result_t = TypeD::make(NAN); ++ } ++ } ++ ++ if (result_t != nullptr) { ++ // We can't simply return a TypeD here, it must be a tuple type to be compatible with call nodes. ++ const Type** fields = TypeTuple::fields(2); ++ fields[TypeFunc::Parms + 0] = result_t; ++ fields[TypeFunc::Parms + 1] = Type::HALF; ++ return TypeTuple::make(TypeFunc::Parms + 2, fields); ++ } ++ ++ return tf()->range(); ++} ++ ++Node* PowDNode::Ideal(PhaseGVN* phase, bool can_reshape) { ++ if (!can_reshape) { ++ return nullptr; // wait for igvn ++ } ++ ++ PhaseIterGVN* igvn = phase->is_IterGVN(); ++ Node* base = this->base(); ++ Node* exp = this->exp(); ++ ++ const Type* t_exp = phase->type(exp); ++ const TypeD* exp_con = t_exp->isa_double_constant(); ++ ++ // Special cases when only the exponent is known: ++ if (exp_con != nullptr) { ++ double e = exp_con->getd(); ++ ++ // If the second argument is 1.0, then the result is the same as the first argument. ++ // i.e., pow(x, 1.0) => x ++ if (e == 1.0) { ++ return make_tuple_of_input_state_and_result(igvn, base); ++ } ++ ++ // If the second argument is 2.0, then strength reduce to multiplications. ++ // i.e., pow(x, 2.0) => x * x ++ if (e == 2.0) { ++ Node* mul = igvn->transform(new MulDNode(base, base)); ++ return make_tuple_of_input_state_and_result(igvn, mul); ++ } ++ ++ // If the second argument is 0.5, the strength reduce to square roots. ++ // i.e., pow(x, 0.5) => sqrt(x) iff x > 0 ++ if (e == 0.5 && Matcher::match_rule_supported(Op_SqrtD)) { ++ Node* ctrl = in(TypeFunc::Control); ++ Node* zero = igvn->zerocon(T_DOUBLE); ++ ++ // According to the API specs, pow(-0.0, 0.5) = 0.0 and sqrt(-0.0) = -0.0. ++ // So pow(-0.0, 0.5) shouldn't be replaced with sqrt(-0.0). ++ // -0.0/+0.0 are both excluded since floating-point comparison doesn't distinguish -0.0 from +0.0. ++ Node* cmp = igvn->register_new_node_with_optimizer(new CmpDNode(base, zero)); ++ Node* test = igvn->register_new_node_with_optimizer(new BoolNode(cmp, BoolTest::le)); ++ ++ IfNode* iff = new IfNode(ctrl, test, PROB_UNLIKELY_MAG(3), COUNT_UNKNOWN); ++ igvn->register_new_node_with_optimizer(iff); ++ Node* if_slow = igvn->register_new_node_with_optimizer(new IfTrueNode(iff)); // x <= 0 ++ Node* if_fast = igvn->register_new_node_with_optimizer(new IfFalseNode(iff)); // x > 0 ++ ++ // slow path: call pow(x, 0.5) ++ Node* call = igvn->register_new_node_with_optimizer(inline_call_leaf_pure_node(if_slow)); ++ Node* call_ctrl = igvn->register_new_node_with_optimizer(new ProjNode(call, TypeFunc::Control)); ++ Node* call_result = igvn->register_new_node_with_optimizer(new ProjNode(call, TypeFunc::Parms + 0)); ++ ++ // fast path: sqrt(x) ++ Node* sqrt = igvn->register_new_node_with_optimizer(new SqrtDNode(igvn->C, if_fast, base)); ++ ++ // merge paths ++ RegionNode* region = new RegionNode(3); ++ igvn->register_new_node_with_optimizer(region); ++ region->init_req(1, call_ctrl); // slow path ++ region->init_req(2, if_fast); // fast path ++ ++ PhiNode* phi = new PhiNode(region, Type::DOUBLE); ++ igvn->register_new_node_with_optimizer(phi); ++ phi->init_req(1, call_result); // slow: pow() result ++ phi->init_req(2, sqrt); // fast: sqrt() result ++ ++ igvn->C->set_has_split_ifs(true); // Has chance for split-if optimization ++ ++ return make_tuple_of_input_state_and_result(igvn, phi, region); ++ } ++ } ++ ++ return CallLeafPureNode::Ideal(phase, can_reshape); ++} ++ ++// We can't simply have Ideal() returning a Con or MulNode since the users are still expecting a Call node, but we could ++// produce a tuple that follows the same pattern so users can still get control, io, memory, etc.. ++TupleNode* PowDNode::make_tuple_of_input_state_and_result(PhaseIterGVN* phase, Node* result, Node* control) { ++ if (control == nullptr) { ++ control = in(TypeFunc::Control); ++ } ++ ++ Compile* C = phase->C; ++ C->remove_macro_node(this); ++ TupleNode* tuple = TupleNode::make( ++ tf()->range(), ++ control, ++ in(TypeFunc::I_O), ++ in(TypeFunc::Memory), ++ in(TypeFunc::FramePtr), ++ in(TypeFunc::ReturnAdr), ++ result, ++ C->top()); ++ return tuple; ++} +diff --git a/src/hotspot/share/opto/callnode.hpp b/src/hotspot/share/opto/callnode.hpp +index 2462a88143f..bb87746a3f6 100644 +--- a/src/hotspot/share/opto/callnode.hpp ++++ b/src/hotspot/share/opto/callnode.hpp +@@ -953,6 +953,8 @@ class CallLeafPureNode : public CallLeafNode { + } + int Opcode() const override; + Node* Ideal(PhaseGVN* phase, bool can_reshape) override; ++ ++ CallLeafPureNode* inline_call_leaf_pure_node(Node* control = nullptr) const; + }; + + //------------------------------CallLeafNoFPNode------------------------------- +@@ -1304,4 +1306,19 @@ class UnlockNode : public AbstractLockNode { + JVMState* dbg_jvms() const { return nullptr; } + #endif + }; ++ ++//------------------------------PowDNode-------------------------------------- ++class PowDNode : public CallLeafPureNode { ++ TupleNode* make_tuple_of_input_state_and_result(PhaseIterGVN* phase, Node* result, Node* control = nullptr); ++ ++public: ++ PowDNode(Compile* C, Node* base, Node* exp); ++ int Opcode() const override; ++ const Type* Value(PhaseGVN* phase) const override; ++ Node* Ideal(PhaseGVN* phase, bool can_reshape) override; ++ ++ Node* base() const { return in(TypeFunc::Parms + 0); } ++ Node* exp() const { return in(TypeFunc::Parms + 2); } ++}; ++ + #endif // SHARE_OPTO_CALLNODE_HPP +diff --git a/src/hotspot/share/opto/classes.hpp b/src/hotspot/share/opto/classes.hpp +index 587d5fad8f2..b7ba16e99a0 100644 +--- a/src/hotspot/share/opto/classes.hpp ++++ b/src/hotspot/share/opto/classes.hpp +@@ -283,6 +283,7 @@ macro(OpaqueZeroTripGuard) + macro(OpaqueNotNull) + macro(OpaqueInitializedAssertionPredicate) + macro(OpaqueTemplateAssertionPredicate) ++macro(PowD) + macro(ProfileBoolean) + macro(OrI) + macro(OrL) +diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp +index 12960d101a8..6c71a61ba75 100644 +--- a/src/hotspot/share/opto/library_call.cpp ++++ b/src/hotspot/share/opto/library_call.cpp +@@ -1817,61 +1817,17 @@ bool LibraryCallKit::runtime_math(const TypeFunc* call_type, address funcAddr, c + + //------------------------------inline_math_pow----------------------------- + bool LibraryCallKit::inline_math_pow() { ++ Node* base = argument(0); + Node* exp = argument(2); +- const TypeD* d = _gvn.type(exp)->isa_double_constant(); +- if (d != nullptr) { +- if (d->getd() == 2.0) { +- // Special case: pow(x, 2.0) => x * x +- Node* base = argument(0); +- set_result(_gvn.transform(new MulDNode(base, base))); +- return true; +- } else if (d->getd() == 0.5 && Matcher::match_rule_supported(Op_SqrtD)) { +- // Special case: pow(x, 0.5) => sqrt(x) +- Node* base = argument(0); +- Node* zero = _gvn.zerocon(T_DOUBLE); +- +- RegionNode* region = new RegionNode(3); +- Node* phi = new PhiNode(region, Type::DOUBLE); +- +- Node* cmp = _gvn.transform(new CmpDNode(base, zero)); +- // According to the API specs, pow(-0.0, 0.5) = 0.0 and sqrt(-0.0) = -0.0. +- // So pow(-0.0, 0.5) shouldn't be replaced with sqrt(-0.0). +- // -0.0/+0.0 are both excluded since floating-point comparison doesn't distinguish -0.0 from +0.0. +- Node* test = _gvn.transform(new BoolNode(cmp, BoolTest::le)); +- +- Node* if_pow = generate_slow_guard(test, nullptr); +- Node* value_sqrt = _gvn.transform(new SqrtDNode(C, control(), base)); +- phi->init_req(1, value_sqrt); +- region->init_req(1, control()); +- +- if (if_pow != nullptr) { +- set_control(if_pow); +- address target = StubRoutines::dpow() != nullptr ? StubRoutines::dpow() : +- CAST_FROM_FN_PTR(address, SharedRuntime::dpow); +- const TypePtr* no_memory_effects = nullptr; +- Node* trig = make_runtime_call(RC_LEAF, OptoRuntime::Math_DD_D_Type(), target, "POW", +- no_memory_effects, base, top(), exp, top()); +- Node* value_pow = _gvn.transform(new ProjNode(trig, TypeFunc::Parms+0)); +-#ifdef ASSERT +- Node* value_top = _gvn.transform(new ProjNode(trig, TypeFunc::Parms+1)); +- assert(value_top == top(), "second value must be top"); +-#endif +- phi->init_req(2, value_pow); +- region->init_req(2, _gvn.transform(new ProjNode(trig, TypeFunc::Control))); +- } +- +- C->set_has_split_ifs(true); // Has chance for split-if optimization +- set_control(_gvn.transform(region)); +- record_for_igvn(region); +- set_result(_gvn.transform(phi)); + +- return true; +- } +- } +- +- return StubRoutines::dpow() != nullptr ? +- runtime_math(OptoRuntime::Math_DD_D_Type(), StubRoutines::dpow(), "dpow") : +- runtime_math(OptoRuntime::Math_DD_D_Type(), CAST_FROM_FN_PTR(address, SharedRuntime::dpow), "POW"); ++ CallNode* pow = new PowDNode(C, base, exp); ++ set_predefined_input_for_runtime_call(pow); ++ pow = _gvn.transform(pow)->as_CallLeafPure(); ++ set_predefined_output_for_runtime_call(pow); ++ Node* result = _gvn.transform(new ProjNode(pow, TypeFunc::Parms + 0)); ++ record_for_igvn(pow); ++ set_result(result); ++ return true; + } + + //------------------------------inline_math_native----------------------------- +diff --git a/src/hotspot/share/opto/macro.cpp b/src/hotspot/share/opto/macro.cpp +index aafc5d3c170..a28043c8d8f 100644 +--- a/src/hotspot/share/opto/macro.cpp ++++ b/src/hotspot/share/opto/macro.cpp +@@ -2484,6 +2484,7 @@ void PhaseMacroExpand::eliminate_macro_nodes() { + assert(n->Opcode() == Op_LoopLimit || + n->Opcode() == Op_ModD || + n->Opcode() == Op_ModF || ++ n->Opcode() == Op_PowD || + n->is_OpaqueNotNull() || + n->is_OpaqueInitializedAssertionPredicate() || + n->Opcode() == Op_MaxL || +@@ -2637,19 +2638,11 @@ bool PhaseMacroExpand::expand_macro_nodes() { + default: + switch (n->Opcode()) { + case Op_ModD: +- case Op_ModF: { +- CallNode* mod_macro = n->as_Call(); +- CallNode* call = new CallLeafPureNode(mod_macro->tf(), mod_macro->entry_point(), +- mod_macro->_name, TypeRawPtr::BOTTOM); +- call->init_req(TypeFunc::Control, mod_macro->in(TypeFunc::Control)); +- call->init_req(TypeFunc::I_O, C->top()); +- call->init_req(TypeFunc::Memory, C->top()); +- call->init_req(TypeFunc::ReturnAdr, C->top()); +- call->init_req(TypeFunc::FramePtr, C->top()); +- for (unsigned int i = 0; i < mod_macro->tf()->domain()->cnt() - TypeFunc::Parms; i++) { +- call->init_req(TypeFunc::Parms + i, mod_macro->in(TypeFunc::Parms + i)); +- } +- _igvn.replace_node(mod_macro, call); ++ case Op_ModF: ++ case Op_PowD: { ++ CallLeafPureNode* call_macro = n->as_CallLeafPure(); ++ CallLeafPureNode* call = call_macro->inline_call_leaf_pure_node(); ++ _igvn.replace_node(call_macro, call); + transform_later(call); + break; + } +diff --git a/test/hotspot/jtreg/compiler/intrinsics/math/PowDNodeTests.java b/test/hotspot/jtreg/compiler/intrinsics/math/PowDNodeTests.java +new file mode 100644 +index 00000000000..e28cc5ab346 +--- /dev/null ++++ b/test/hotspot/jtreg/compiler/intrinsics/math/PowDNodeTests.java +@@ -0,0 +1,218 @@ ++/* ++ * Copyright (c) 2026, IBM and/or its affiliates. All rights reserved. ++ * 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.intrinsics.math; ++ ++import jdk.test.lib.Asserts; ++ ++import compiler.lib.ir_framework.*; ++import compiler.lib.generators.*; ++import static compiler.lib.generators.Generators.*; ++ ++import java.util.Random; ++ ++/* ++ * @test ++ * @bug 8378713 ++ * @key randomness ++ * @summary Math.pow(base, exp) should constant propagate ++ * @library /test/lib / ++ * @run driver ${test.main.class} ++ */ ++public class PowDNodeTests { ++ public static final Generator UNIFORMS = G.uniformDoubles(); // [0, 1) ++ ++ public static final double B = UNIFORMS.next() * 1000.0d; ++ public static final double E = UNIFORMS.next() * 1000.0d + 3.0d; // e >= 3 to avoid strength reduction code ++ ++ public static void main(String[] args) { ++ TestFramework.run(); ++ ++ testCorrectness(); ++ } ++ ++ // Test 1: pow(2.0, 10.0) -> 1024.0 ++ @Test ++ @IR(failOn = {IRNode.POW_D}) ++ public static double constantLiteralFolding() { ++ return Math.pow(2.0, 10.0); // should fold to 1024.0 ++ } ++ ++ // Test 2: pow(final B, final E) -> B^E ++ @Test ++ @IR(failOn = {IRNode.POW_D}) ++ public static double constantStaticFolding() { ++ return Math.pow(B, E); // should fold to B^E ++ } ++ ++ // Test 3: pow(b, 0.0) -> 1.0 ++ @Test ++ @IR(failOn = {IRNode.POW_D}) ++ @Arguments(values = {Argument.RANDOM_EACH}) ++ public static double expZero(double b) { ++ return Math.pow(b, 0.0); ++ } ++ ++ // Test 4: pow(b, 1.0) -> b (identity) ++ @Test ++ @IR(failOn = {IRNode.POW_D}) ++ @Arguments(values = {Argument.RANDOM_EACH}) ++ public static double expOne(double b) { ++ return Math.pow(b, 1.0); ++ } ++ ++ // Test 5: pow(b, NaN) -> NaN ++ @Test ++ @IR(failOn = {IRNode.POW_D}) ++ @Arguments(values = {Argument.RANDOM_EACH}) ++ public static double expNaN(double b) { ++ return Math.pow(b, Double.NaN); ++ } ++ ++ // Test 6: pow(b, 2.0) -> b * b ++ // More tests in TestPow2Opt.java ++ @Test ++ @IR(failOn = {IRNode.POW_D}) ++ @IR(counts = {IRNode.MUL_D, "1"}) ++ @Arguments(values = {Argument.RANDOM_EACH}) ++ public static double expTwo(double b) { ++ return Math.pow(b, 2.0); ++ } ++ ++ // Test 7: pow(b, 0.5) -> b <= 0.0 ? pow(b, 0.5) : sqrt(b) ++ // More tests in TestPow0Dot5Opt.java ++ @Test ++ @IR(counts = {IRNode.IF, "1"}) ++ @IR(counts = {IRNode.SQRT_D, "1"}) ++ @IR(counts = {".*CallLeaf.*pow.*", "1"}, phase = CompilePhase.BEFORE_MATCHING) ++ @Arguments(values = {Argument.RANDOM_EACH}) ++ public static double expDot5(double b) { ++ return Math.pow(b, 0.5); // expand to: if (b > 0) { sqrt(b) } else { call(b) } ++ } ++ ++ // Test 8: non-constant exponent stays as call ++ @Test ++ @IR(counts = {IRNode.POW_D, "1"}) ++ @Arguments(values = {Argument.RANDOM_EACH, Argument.RANDOM_EACH}) ++ public static double nonConstant(double b, double e) { ++ return Math.pow(b, e); ++ } ++ ++ // Test 9: late constant discovery on base (after loop opts) ++ @Test ++ @IR(counts = {IRNode.POW_D, "1"}, phase = CompilePhase.AFTER_PARSING) ++ @IR(failOn = {IRNode.POW_D}) ++ public static double lateBaseConstant() { ++ double base = 0; ++ for (int i = 0; i < 4; i++) { ++ if ((i % 2) == 0) { ++ base = B; ++ } ++ } ++ // After loop opts, base == B (constant), so pow(B, E) folds ++ return Math.pow(base, E); ++ } ++ ++ // Test 10: late constant discovery on exp (after loop opts) ++ @Test ++ @IR(counts = {IRNode.POW_D, "1"}, phase = CompilePhase.AFTER_PARSING) ++ @IR(failOn = {IRNode.POW_D}) ++ public static double lateExpConstant() { ++ double exp = 0; ++ for (int i = 0; i < 4; i++) { ++ if ((i % 2) == 0) { ++ exp = E; ++ } ++ } ++ // After loop opts, exp == E (constant), so pow(B, E) folds ++ return Math.pow(B, exp); ++ } ++ ++ // Test 11: late constant discoveries on both base and exp (after loop opts) ++ @Test ++ @IR(counts = {IRNode.POW_D, "1"}, phase = CompilePhase.AFTER_PARSING) ++ @IR(failOn = {IRNode.POW_D}) ++ public static double lateBothConstant() { ++ double base = 0, exp = 0; ++ for (int i = 0; i < 4; i++) { ++ if ((i % 2) == 0) { ++ base = B; ++ exp = E; ++ } ++ } ++ // After loop opts, base = B, exp == E, so pow(B, E) folds ++ return Math.pow(base, exp); ++ } ++ ++ private static void assertEQWithinOneUlp(double expected, double observed) { ++ if (Double.isNaN(expected) && Double.isNaN(observed)) return; ++ ++ // Math.pow() requires result must be within 1 ulp of the respective magnitude ++ double ulp = Math.max(Math.ulp(expected), Math.ulp(observed)); ++ if (Math.abs(expected - observed) > ulp) { ++ throw new AssertionError(String.format( ++ "expect = %x, observed = %x, ulp = %x", ++ Double.doubleToRawLongBits(expected), Double.doubleToRawLongBits(observed), Double.doubleToRawLongBits(ulp) ++ )); ++ } ++ } ++ ++ private static void testCorrectness() { ++ // No need to warm up for intrinsics ++ Asserts.assertEQ(1024.0d, constantLiteralFolding()); ++ ++ double BE = StrictMath.pow(B, E); ++ assertEQWithinOneUlp(BE, constantStaticFolding()); ++ assertEQWithinOneUlp(BE, lateBaseConstant()); ++ assertEQWithinOneUlp(BE, lateExpConstant()); ++ assertEQWithinOneUlp(BE, lateBothConstant()); ++ ++ Generator anyBits = G.anyBitsDouble(); ++ Generator largeDoubles = G.uniformDoubles(Long.MAX_VALUE, Double.MAX_VALUE); ++ Generator doubles = G.doubles(); ++ double[] values = { ++ Double.MIN_VALUE, Double.MIN_NORMAL, -42.0d, -1.0d, -0.0d, +0.0d, 0.5d, 1.0d, 2.0d, 123d, Double.MAX_VALUE, ++ Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, Double.NaN, ++ UNIFORMS.next(), UNIFORMS.next(), ++ largeDoubles.next(), -largeDoubles.next(), // some sufficiently large magnitudes ++ anyBits.next(), anyBits.next(), // any bits with potentially more NaN representation ++ doubles.next(), doubles.next() // a healthy sprinkle of whatever else is possible ++ }; ++ ++ for (double b : values) { ++ // Strength reduced, so we know the bits matches exactly ++ Asserts.assertEQ(1.0d, expZero(b)); ++ Asserts.assertEQ(b, expOne(b)); ++ Asserts.assertEQ(b * b, expTwo(b)); ++ ++ assertEQWithinOneUlp(Double.NaN, expNaN(b)); ++ ++ // Runtime calls, so make sure the result is within 1 ulp ++ assertEQWithinOneUlp(StrictMath.pow(b, 0.5d), expDot5(b)); ++ ++ for (double e : values) { ++ assertEQWithinOneUlp(StrictMath.pow(b, e), nonConstant(b, e)); ++ } ++ } ++ } ++} +diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +index 7b751f1a72c..6a95a2b5da7 100644 +--- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java ++++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +@@ -1858,6 +1858,11 @@ public class IRNode { + beforeMatchingNameRegex(SQRT_HF, "SqrtHF"); + } + ++ public static final String SQRT_D = PREFIX + "SQRT_D" + POSTFIX; ++ static { ++ beforeMatchingNameRegex(SQRT_D, "SqrtD"); ++ } ++ + public static final String SQRT_F = PREFIX + "SQRT_F" + POSTFIX; + static { + beforeMatchingNameRegex(SQRT_F, "SqrtF"); +@@ -2825,6 +2830,12 @@ public class IRNode { + macroNodes(MOD_D, regex); + } + ++ public static final String POW_D = PREFIX + "POW_D" + POSTFIX; ++ static { ++ String regex = START + "PowD" + MID + END; ++ macroNodes(POW_D, regex); ++ } ++ + public static final String BLACKHOLE = PREFIX + "BLACKHOLE" + POSTFIX; + static { + fromBeforeRemoveUselessToFinalCode(BLACKHOLE, "Blackhole"); +-- +2.53.0 + diff --git a/sources b/sources index 3c199f6..c4a7c33 100644 --- a/sources +++ b/sources @@ -1,3 +1,3 @@ SHA512 (nssadapter-0.1.1.tar.xz) = 2b4675cfbfa2ccb6c9a4870a4b58ae555267f5b8c9bdb0cf37b075483e6e9ea929561c05070453cf0d67b0b029de5408274555bf2ff50e9533219e898b2717f9 -SHA512 (openjdk-25.0.3+9.tar.xz) = 382dcf42ede35c7e48e0f9403d30172e6bc6367517e0c49211ab9d2e43373c3d7e586969c27795f0bfd17ae5c9f00702e955495a31d7ea757f54f06e8a4cf113 +SHA512 (openjdk-25.0.4+7.tar.xz) = bd2c336ba2f0196e361bc8fd81a39cd9907682c0fac3a2b24a703a2abcede0fc75247fc54767329fc45d2f562f2728e3691db864363e9ab326c8218280831494 SHA512 (tapsets-icedtea-6.0.0pre00-c848b93a8598.tar.xz) = 97d026212363b3c83f6a04100ad7f6fdde833d16579717f8756e2b8c2eb70e144a41a330cb9ccde9c3badd37a2d54fdf4650a950ec21d8b686d545ecb2a64d30