public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
From: Jiri Vanek <jvanek@redhat.com>
To: git-commits@fedoraproject.org
Subject: [rpms/java-25-openjdk-portable] f44: Updated to OpenJDK 25.0.4 (2026-07-21)
Date: Fri, 24 Jul 2026 13:21:18 GMT	[thread overview]
Message-ID: <178489927804.1.2946838008358768204.rpms-java-25-openjdk-portable-5a268016ad90@fedoraproject.org> (raw)

            A new commit has been pushed.

            Repo   : rpms/java-25-openjdk-portable
            Branch : f44
            Commit : 5a268016ad909c415222f9453d4b2bcf17a48561
            Author : Jiri Vanek <jvanek@redhat.com>
            Date   : 2026-07-24T15:18:32+02:00
            Stats  : +1933/-310 in 9 file(s)
            URL    : https://src.fedoraproject.org/rpms/java-25-openjdk-portable/c/5a268016ad909c415222f9453d4b2bcf17a48561?branch=f44

            Log:
            Updated to OpenJDK 25.0.4 (2026-07-21)

Rearranged specfile for better readability and removed unused macros,
which were kept only for rpms synchronization which is obsoleted.
Improved TestTransaltions (gnu_andrew)

---
diff --git a/.gitignore b/.gitignore
index f57f28e..a4b4322 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,3 +6,4 @@
 /openjdk-25.0.1+8.tar.xz
 /openjdk-25.0.2+10.tar.xz
 /openjdk-25.0.3+9.tar.xz
+/openjdk-25.0.4+7.tar.xz

diff --git a/NEWS b/NEWS
index e009ba8..622c8fa 100644
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,361 @@ 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
+  - CVE-2026-46968
+  - CVE-2026-46917
+  - CVE-2026-47010
+  - CVE-2026-47021
+  - CVE-2026-47027
+  - CVE-2026-60147
+  - CVE-2026-47059
+  - CVE-2026-47063
+  - CVE-2026-41254
+* 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 <pid> 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<Locale,String[]> exp, String[] ids) {
+    private static void testZone(Map<Locale,String[]> 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.spec b/java-25-openjdk-portable.spec
index 833fd91..ced8d56 100644
--- a/java-25-openjdk-portable.spec
+++ b/java-25-openjdk-portable.spec
@@ -1,4 +1,98 @@
-# 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 2
+%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<dist> for EA releases,
+# - N<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
+
+%global compatiblename  java-%{javaver}-%{origin}
+
+Name:    java-25-%{origin}-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
+# Automatically converted from old format: 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 - review is highly recommended.
+License:  Apache-1.1 AND Apache-2.0 AND LicenseRef-Callaway-BSD AND LicenseRef-Callaway-BSD-with-advertising AND GPL-1.0-or-later AND GPL-2.0-only AND LicenseRef-Callaway-GPLv2-with-exceptions AND IJG AND LicenseRef-Callaway-LGPLv2+ AND LicenseRef-Callaway-MIT AND MPL-2.0 AND LicenseRef-Callaway-Public-Domain AND W3C AND Zlib AND ISC AND FTL AND LicenseRef-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
@@ -15,7 +109,6 @@
 #
 # Only produce a release build on x86_64:
 # $ fedpkg mockbuild --without slowdebug --without fastdebug
-
 # Enable fastdebug builds by default on relevant arches.
 %bcond_without fastdebug
 # Enable slowdebug builds by default on relevant arches.
@@ -24,8 +117,6 @@
 %bcond_without release
 # Enable static library builds by default.
 %bcond_without staticlibs
-# Remove build artifacts by default
-%bcond_with artifacts
 # Build a fresh libjvm.so for use in a copy of the bootstrap JDK
 %bcond_without fresh_libjvm
 # Build with system libraries
@@ -99,25 +190,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_ -e alternatives
-# 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
@@ -403,17 +475,14 @@ exit 1
 %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 25
+%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}
@@ -425,7 +494,8 @@ exit 1
 # 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=%{component}&version=epel%{epel}
@@ -441,67 +511,13 @@ exit 1
 %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 miscinstalloutputdir install
@@ -522,31 +538,33 @@ exit 1
 %define jdkportablenameimpl() %(echo %{uniquesuffix ""} | sed "s;%{regexBase};\\0.portable%{1}.jdk;g" | sed "s;openjdkportable;el;g")
 %define jdkportablesourcesnameimpl() %(echo %{uniquesuffix ""} | sed "s;%{regexBase};\\0.portable%{1}.sources;g" | sed "s;openjdkportable;el;g" | sed "s;.%{_arch};.noarch;g")
 %define staticlibsportablenameimpl() %(echo %{uniquesuffix ""} | sed "s;%{regexBase};\\0.portable%{1}.static-libs;g" | sed "s;openjdkportable;el;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 jmodsportablenameimpl() %(echo %{uniquesuffix ""} | sed "s;%{regexBase};\\0.portable%{1}.jmods;g" | sed "s;openjdkportable;el;g")
 %define jreportablearchive()  %{expand:%{jreportablenameimpl -- %%{1}}.tar.xz}
+%define jreportablearchive_for_files()  %(echo %{jreportablearchive -- ""})
 %define jdkportablearchive()  %{expand:%{jdkportablenameimpl -- %%{1}}.tar.xz}
-%define jdkportablesourcesarchive()  %{expand:%{jdkportablesourcesnameimpl -- %%{1}}.tar.xz}
+%define jdkportablearchive_for_files()  %(echo %{jdkportablearchive -- ""})
 %define staticlibsportablearchive()  %{expand:%{staticlibsportablenameimpl -- %%{1}}.tar.xz}
+%define staticlibsportablearchive_for_files()  %(echo %{staticlibsportablearchive -- ""})
+%define jdkportablesourcesarchive()  %{expand:%{jdkportablesourcesnameimpl -- %%{1}}.tar.xz}
+%define jdkportablesourcesname()     %{expand:%{jdkportablesourcesnameimpl -- %%{1}}}
+%define jdkportablesourcesarchive_for_files()  %(echo %{jdkportablesourcesarchive -- ""})
 %define jmodsportablearchive()  %{expand:%{jmodsportablenameimpl -- %%{1}}.tar.xz}
+%define jmodsportablearchive_for_files()  %(echo %{jmodsportablearchive -- ""})
 %define jreportablename()     %{expand:%{jreportablenameimpl -- %%{1}}}
 %define jdkportablename()     %{expand:%{jdkportablenameimpl -- %%{1}}}
-%define jdkportablesourcesname()     %{expand:%{jdkportablesourcesnameimpl -- %%{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}}}
+
+# These macros are not parameterised as the same is shared by all builds
 %define docportablename() %(echo %{uniquesuffix ""} | sed "s;%{regexBase};\\0.portable.docs;g" | sed "s;openjdkportable;el;g")
 %define docportablearchive()  %{docportablename}.tar.xz
 %define miscportablename() %(echo %{uniquesuffix ""} | sed "s;%{regexBase};\\0.portable.misc;g" | sed "s;openjdkportable;el;g")
 %define miscportablearchive()  %{miscportablename}.tar.xz
 
-# 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
-%define jreportablearchiveForFiles()  %(echo %{jreportablearchive -- ""})
-%define jdkportablearchiveForFiles()  %(echo %{jdkportablearchive -- ""})
-%define jdkportablesourcesarchiveForFiles()  %(echo %{jdkportablesourcesarchive -- ""})
-%define staticlibsportablearchiveForFiles()  %(echo %{staticlibsportablearchive -- ""})
-%define jmodsportablearchiveForFiles()  %(echo %{jmodsportablearchive -- ""})
-
 # JDK to use for bootstrapping
 %ifarch %{fastdebug_arches}
 %global bootdebugpkg fastdebug
@@ -570,26 +588,6 @@ exit 1
 %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 any debug 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
@@ -597,28 +595,11 @@ exit 1
 %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 generated_sources_name     generated_sources
 
 %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
@@ -653,51 +634,13 @@ ExcludeArch: %{ix86}
 ExclusiveArch:  %{exclusive_arches}
 %endif
 
-Name:    java-25-%{origin}-portable%{?pkgos:-%{pkgos}}
-Version: %{newjavaver}.%{buildver}
-Release: %{?eaprefix}%{rpmrelease}%{?extraver}%{?dist}.1
-# 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
-# Automatically converted from old format: 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 - review is highly recommended.
-License:  Apache-1.1 AND Apache-2.0 AND LicenseRef-Callaway-BSD AND LicenseRef-Callaway-BSD-with-advertising AND GPL-1.0-or-later AND GPL-2.0-only AND LicenseRef-Callaway-GPLv2-with-exceptions AND IJG AND LicenseRef-Callaway-LGPLv2+ AND LicenseRef-Callaway-MIT AND MPL-2.0 AND LicenseRef-Callaway-Public-Domain AND W3C AND Zlib AND ISC AND FTL AND LicenseRef-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
 
 # Use 'icedtea_sync.sh' to update the following
 # They are based on code contained in the IcedTea project (6.x).
 # Systemtap tapsets. Zipped up to keep it small.
-# Disabled in portables
+# Disabled in fedora portables (applied in fedora rpms)
 #Source8: tapsets-icedtea-%%{icedteaver}.tar.xz
 
 # Desktop files. Adapted from IcedTea
@@ -733,12 +676,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 <vcstag> src make test > fips-25u-$(git show -s --format=%h HEAD).patch
 # Diff is limited to src and make subdirectories to exclude .github changes
-# The following list is generated by:
-# git log %%{vcstag}.. --no-merges --format=%s --reverse:
+
 # Fixes currently included:
 # OPENJDK-2108: Internal __redhat_fips__ property
 # OPENJDK-2123: Algorithms lockdown
@@ -751,8 +695,7 @@ 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
+# Currently empty
 
 #############################################
 #
@@ -760,7 +703,10 @@ Patch2001: jdk8375294-handle-EOPNOTSUPP-in-copying.patch
 #
 #############################################
 
-# Currently empty
+# 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
 
 #############################################
 #
@@ -831,17 +777,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
@@ -1025,37 +971,22 @@ 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
+
 %if %{system_libs}
 # Remove libraries that are linked by both static and dynamic builds
 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"
@@ -1124,7 +1055,6 @@ fi
 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"
@@ -1864,8 +1794,8 @@ done
 %if %{include_normal_build}
 %files
 # main package builds always
-%{_jvmdir}/%{jreportablearchiveForFiles}
-%{_jvmdir}/%{jreportablearchiveForFiles}.sha256sum
+%{_jvmdir}/%{jreportablearchive_for_files}
+%{_jvmdir}/%{jreportablearchive_for_files}.sha256sum
 %else
 %files
 # placeholder
@@ -1873,19 +1803,19 @@ done
 
 %if %{include_normal_build}
 %files devel
-%{_jvmdir}/%{jdkportablearchiveForFiles}
+%{_jvmdir}/%{jdkportablearchive_for_files}
 %{_jvmdir}/%{jdkportablearchive -- .debuginfo}
-%{_jvmdir}/%{jdkportablearchiveForFiles}.sha256sum
+%{_jvmdir}/%{jdkportablearchive_for_files}.sha256sum
 %{_jvmdir}/%{jdkportablearchive -- .debuginfo}.sha256sum
-%{_jvmdir}/%{jmodsportablearchiveForFiles}
-%{_jvmdir}/%{jmodsportablearchiveForFiles}.sha256sum
+%{_jvmdir}/%{jmodsportablearchive_for_files}
+%{_jvmdir}/%{jmodsportablearchive_for_files}.sha256sum
 %endif
 
 %if %{include_normal_build}
 %if %{include_staticlibs}
 %files static-libs
-%{_jvmdir}/%{staticlibsportablearchiveForFiles}
-%{_jvmdir}/%{staticlibsportablearchiveForFiles}.sha256sum
+%{_jvmdir}/%{staticlibsportablearchive_for_files}
+%{_jvmdir}/%{staticlibsportablearchive_for_files}.sha256sum
 %endif
 %endif
 
@@ -1926,8 +1856,8 @@ done
 %endif
 
 %files sources
-%{_jvmdir}/%{jdkportablesourcesarchiveForFiles}
-%{_jvmdir}/%{jdkportablesourcesarchiveForFiles}.sha256sum
+%{_jvmdir}/%{jdkportablesourcesarchive_for_files}
+%{_jvmdir}/%{jdkportablesourcesarchive_for_files}.sha256sum
 
 %if %{include_normal_build}
 %files docs

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 <duke@openjdk.org>
+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 <math.h>
+ 
+-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<TypeLong, julong, jlong>(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 <typename... NN>
++  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 <typename... NN>
++  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<CallNode*>(new ModDNode(C, a, b)) : new ModFNode(C, a, b);
++  CallLeafPureNode* mod = type == BasicType::T_DOUBLE ? static_cast<CallLeafPureNode*>(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?= <jvanek@openjdk.org>
-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 <kxu@redhat.com>
+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<Double> 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<Double> anyBits = G.anyBitsDouble();
++        Generator<Double> largeDoubles = G.uniformDoubles(Long.MAX_VALUE, Double.MAX_VALUE);
++        Generator<Double> 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/scripts/generate_source_tarball.sh b/scripts/generate_source_tarball.sh
index eeded5c..56afb4d 100755
--- a/scripts/generate_source_tarball.sh
+++ b/scripts/generate_source_tarball.sh
@@ -48,7 +48,7 @@
 # This will check out the same version as example 1, but from the
 # upstream repository:
 #
-# $ VERSION=jdk-25.0.3+9 PROJECT_NAME=openjdk REPO_NAME=jdk25u \
+# $ VERSION=jdk-25.0.4+7 PROJECT_NAME=openjdk REPO_NAME=jdk25u \
 #   BOOT_JDK=/usr/lib/jvm/java-25-openjdk sh scripts/generate_source_tarball.sh
 #
 # Example 3:

diff --git a/sources b/sources
index 278d6f4..dfb2c05 100644
--- a/sources
+++ b/sources
@@ -1 +1 @@
-SHA512 (openjdk-25.0.3+9.tar.xz) = 382dcf42ede35c7e48e0f9403d30172e6bc6367517e0c49211ab9d2e43373c3d7e586969c27795f0bfd17ae5c9f00702e955495a31d7ea757f54f06e8a4cf113
+SHA512 (openjdk-25.0.4+7.tar.xz) = 736949ba57d6e36df1b4f85418b2a27d3e0aec7e4b492ef5d9c006355ede63db3f5f9e0e0ea2d63bea119d9baaa9cf5a92e14dad19e69e9351072ef0955ea2cf

                 reply	other threads:[~2026-07-24 13:21 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=178489927804.1.2946838008358768204.rpms-java-25-openjdk-portable-5a268016ad90@fedoraproject.org \
    --to=jvanek@redhat.com \
    --cc=git-commits@fedoraproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox