From 21482fa7dba9aa649a37abe640910eda9d505b85 Mon Sep 17 00:00:00 2001 From: Patricio Chilano Mateo Date: Mon, 8 Jun 2026 19:15:56 +0000 Subject: [PATCH 01/18] 8385806: Assert failed when running Skynet.java with continuation trace logging enabled Reviewed-by: fbredberg, coleenp --- src/hotspot/share/runtime/frame.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/hotspot/share/runtime/frame.cpp b/src/hotspot/share/runtime/frame.cpp index a1c33f4fda0..b983b4648d4 100644 --- a/src/hotspot/share/runtime/frame.cpp +++ b/src/hotspot/share/runtime/frame.cpp @@ -1237,9 +1237,6 @@ void frame::interpreter_frame_verify_monitor(BasicObjectLock* value) const { #ifndef PRODUCT -// Returns true iff the address p is readable and *(intptr_t*)p != errvalue -extern "C" bool dbg_is_safe(const void* p, intptr_t errvalue); - class FrameValuesOopClosure: public OopClosure, public DerivedOopClosure { private: GrowableArray* _oops; @@ -1269,17 +1266,13 @@ public: _derived->push(derived_loc); } - bool is_good(oop* p) { - return *p == nullptr || (dbg_is_safe(*p, -1) && dbg_is_safe((*p)->klass_without_asserts(), -1) && oopDesc::is_oop_or_null(*p)); - } void describe(FrameValues& values, int frame_no) { for (int i = 0; i < _oops->length(); i++) { oop* p = _oops->at(i); - values.describe(frame_no, (intptr_t*)p, err_msg("oop%s for #%d", is_good(p) ? "" : " (BAD)", frame_no)); + values.describe(frame_no, (intptr_t*)p, err_msg("oop for #%d", frame_no)); } for (int i = 0; i < _narrow_oops->length(); i++) { narrowOop* p = _narrow_oops->at(i); - // we can't check for bad compressed oops, as decoding them might crash values.describe(frame_no, (intptr_t*)p, err_msg("narrow oop for #%d", frame_no)); } assert(_base->length() == _derived->length(), "should be the same"); From bf344f1b9a8ac3069b994b7fe7c91b8c671a9dbd Mon Sep 17 00:00:00 2001 From: Patrick Fontanilla Date: Mon, 8 Jun 2026 21:21:58 +0000 Subject: [PATCH 02/18] 8385933: GenShen: Remove ShenandoahAgingCyclePeriod Reviewed-by: wkemper, ruili, kdnilsen --- .../gc/shenandoah/shenandoahConcurrentGC.cpp | 10 ++-------- .../shenandoahGenerationalControlThread.cpp | 16 +--------------- .../shenandoahGenerationalControlThread.hpp | 6 ------ .../shenandoah/shenandoahGenerationalFullGC.cpp | 6 +----- .../gc/shenandoah/shenandoahGenerationalHeap.cpp | 4 ++-- .../gc/shenandoah/shenandoahGenerationalHeap.hpp | 11 ----------- .../share/gc/shenandoah/shenandoah_globals.hpp | 4 ---- 7 files changed, 6 insertions(+), 51 deletions(-) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp index 07eb653bc94..08032b224d0 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp @@ -1203,19 +1203,13 @@ void ShenandoahConcurrentGC::op_final_update_refs() { heap->verifier()->verify_roots_in_to_space(_generation); } - // If we are running in generational mode and this is an aging cycle, this will also age active - // regions that haven't been used for allocation. + // If we are running in generational mode, this will also age active regions that + // haven't been used for allocation. heap->update_heap_region_states(true /*concurrent*/); heap->set_update_refs_in_progress(false); heap->set_has_forwarded_objects(false); - if (heap->mode()->is_generational() && heap->is_concurrent_old_mark_in_progress()) { - // Aging_cycle is only relevant during evacuation cycle for individual objects and during final mark for - // entire regions. Both of these relevant operations occur before final update refs. - ShenandoahGenerationalHeap::heap()->set_aging_cycle(false); - } - if (ShenandoahVerify) { ShenandoahTimingsTracker v(ShenandoahPhaseTimings::final_update_refs_verify); heap->verifier()->verify_after_update_refs(_generation); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp index 94f3409ac41..f522a33a31c 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp @@ -53,8 +53,7 @@ ShenandoahGenerationalControlThread::ShenandoahGenerationalControlThread() : _requested_generation(nullptr), _gc_mode(none), _degen_point(ShenandoahGC::_degenerated_unset), - _heap(ShenandoahGenerationalHeap::heap()), - _age_period(0) { + _heap(ShenandoahGenerationalHeap::heap()) { shenandoah_assert_generational(); set_name("ShenControl"); create_and_start(); @@ -230,15 +229,6 @@ void ShenandoahGenerationalControlThread::maybe_print_young_region_ages() const } } -void ShenandoahGenerationalControlThread::maybe_set_aging_cycle() { - if (_age_period-- == 0) { - _heap->set_aging_cycle(true); - _age_period = ShenandoahAgingCyclePeriod - 1; - } else { - _heap->set_aging_cycle(false); - } -} - void ShenandoahGenerationalControlThread::run_gc_cycle(const ShenandoahGCRequest& request) { log_debug(gc, thread)("Starting GC (%s): %s, %s", gc_mode_name(gc_mode()), GCCause::to_string(request.cause), request.generation->name()); @@ -534,9 +524,6 @@ void ShenandoahGenerationalControlThread::service_concurrent_cycle(ShenandoahGen // At this point: // if (generation == YOUNG), this is a normal young cycle or a bootstrap cycle // if (generation == GLOBAL), this is a GLOBAL cycle - // In either case, we want to age old objects if this is an aging cycle - maybe_set_aging_cycle(); - ShenandoahGCSession session(cause, generation); TraceCollectorStats tcs(_heap->monitoring_support()->concurrent_collection_counters()); @@ -615,7 +602,6 @@ bool ShenandoahGenerationalControlThread::check_cancellation_or_degen(Shenandoah void ShenandoahGenerationalControlThread::service_stw_full_cycle(GCCause::Cause cause) { _heap->increment_total_collections(true); ShenandoahGCSession session(cause, _heap->global_generation()); - maybe_set_aging_cycle(); ShenandoahFullGC gc; gc.collect(cause); _degen_point = ShenandoahGC::_degenerated_unset; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.hpp index 13e69d25268..5a3ab25eabe 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.hpp @@ -80,9 +80,6 @@ private: // A reference to the heap ShenandoahGenerationalHeap* _heap; - // This is used to keep track of whether to age objects during the current cycle. - uint _age_period; - // This is true when the old generation cycle is in an interruptible phase (i.e., marking or // preparing for mark). ShenandoahSharedFlag _allow_old_preemption; @@ -142,9 +139,6 @@ private: void notify_control_thread(GCCause::Cause cause, ShenandoahGeneration* generation); void notify_control_thread(MonitorLocker& ml, GCCause::Cause cause, ShenandoahGeneration* generation); - // Configure the heap to age objects and regions if the aging period has elapsed. - void maybe_set_aging_cycle(); - // Take the _control_lock and check for a request to run a gc cycle. If a request is found, // the `prepare` methods are used to configure the heap and update heuristics accordingly. void check_for_request(ShenandoahGCRequest& request); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.cpp index 1b11c696d18..43dbddda9f7 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.cpp @@ -312,11 +312,7 @@ void ShenandoahPrepareForGenerationalCompactionObjectClosure::do_object(oop p) { // After full gc compaction, all regions have age 0. Embed the region's age into the object's age in order to preserve // tenuring progress. - if (_heap->is_aging_cycle()) { - ShenandoahHeap::increase_object_age(p, from_region_age + 1); - } else { - ShenandoahHeap::increase_object_age(p, from_region_age); - } + ShenandoahHeap::increase_object_age(p, from_region_age + 1); if (_young_compact_point + obj_size > _young_to_region->end()) { ShenandoahHeapRegion* new_to_region; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp index 4af2c9b1e5d..7170c88cd43 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.cpp @@ -347,7 +347,7 @@ oop ShenandoahGenerationalHeap::try_evacuate_object(oop p, Thread* thread, uint oop copy_val = cast_to_oop(copy); // Update the age of the evacuated object - if (TO_GENERATION == YOUNG_GENERATION && is_aging_cycle()) { + if (TO_GENERATION == YOUNG_GENERATION) { increase_object_age(copy_val, from_region_age + 1); } @@ -975,7 +975,7 @@ public: // There have been allocations in this region since the start of the cycle. // Any objects new to this region must not assimilate elevated age. r->reset_age(); - } else if (ShenandoahGenerationalHeap::heap()->is_aging_cycle()) { + } else { r->increment_age(); } } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.hpp index d6893dc011e..91e5522de43 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalHeap.hpp @@ -61,21 +61,10 @@ public: private: // ---------- Evacuations and Promotions - // - // True when regions and objects should be aged during the current cycle - ShenandoahSharedFlag _is_aging_cycle; // Age census used for adapting tenuring threshold ShenandoahAgeCensus* _age_census; public: - void set_aging_cycle(bool cond) { - _is_aging_cycle.set_cond(cond); - } - - inline bool is_aging_cycle() const { - return _is_aging_cycle.is_set(); - } - // Return the age census object for young gen ShenandoahAgeCensus* age_census() const { return _age_census; diff --git a/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp b/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp index aa6b71a7c50..3647a818490 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp @@ -529,10 +529,6 @@ "Allow young generation collections to suspend concurrent" \ " marking in the old generation.") \ \ - product(uintx, ShenandoahAgingCyclePeriod, 1, EXPERIMENTAL, \ - "With generational mode, increment the age of objects and" \ - "regions each time this many young-gen GC cycles are completed.") \ - \ develop(bool, ShenandoahEnableCardStats, false, \ "Enable statistics collection related to clean & dirty cards") \ \ From 1c1a13085620a604b5668df4a26f4b09a704ceb5 Mon Sep 17 00:00:00 2001 From: David Holmes Date: Mon, 8 Jun 2026 22:01:56 +0000 Subject: [PATCH 03/18] 8384844: Remove expired flags in JDK 28 Reviewed-by: jwilhelm, kvn, syan, jsikstro --- src/hotspot/share/runtime/arguments.cpp | 19 ------------- src/java.base/share/man/java.md | 38 ++++++++++++++----------- 2 files changed, 21 insertions(+), 36 deletions(-) diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index dc177bdce6d..2804224ed01 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -544,25 +544,6 @@ static SpecialFlag const special_jvm_flags[] = { { "UseCompressedClassPointers", JDK_Version::jdk(25), JDK_Version::jdk(27), JDK_Version::undefined() }, #endif - { "PSChunkLargeArrays", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - { "ParallelRefProcEnabled", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - { "ParallelRefProcBalancingEnabled", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - { "MaxRAM", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - { "NewSizeThreadIncrease", JDK_Version::undefined(), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - { "NeverActAsServerClassMachine", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - { "AlwaysActAsServerClassMachine", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - { "UseXMMForArrayCopy", JDK_Version::undefined(), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - { "UseNewLongLShift", JDK_Version::undefined(), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - { "AggressiveHeap", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - - {"ShenandoahAccelerationSamplePeriod", JDK_Version::undefined(), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - {"ShenandoahRateAccelerationSampleSize", JDK_Version::undefined(), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - {"ShenandoahMomentaryAllocationRateSpikeSampleSize", JDK_Version::undefined(), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - {"ShenandoahAdaptiveSampleFrequencyHz", JDK_Version::undefined(), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - {"ShenandoahAdaptiveSampleSizeSeconds", JDK_Version::undefined(), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - {"ShenandoahAdaptiveInitialSpikeThreshold",JDK_Version::undefined(), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - {"ShenandoahAdaptiveDecayFactor", JDK_Version::undefined(), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - #ifdef ASSERT { "DummyObsoleteTestFlag", JDK_Version::undefined(), JDK_Version::jdk(18), JDK_Version::undefined() }, #endif diff --git a/src/java.base/share/man/java.md b/src/java.base/share/man/java.md index 70824046824..ef99084018d 100644 --- a/src/java.base/share/man/java.md +++ b/src/java.base/share/man/java.md @@ -2997,14 +2997,6 @@ they're used. : Enables the use of Java Flight Recorder (JFR) during the runtime of the application. Since JDK 8u40 this option has not been required to use JFR. -[`-XX:+ParallelRefProcEnabled`]{#-XX__ParallelRefProcEnabled} -: Enables parallel reference processing. By default, collectors employing multiple - threads perform parallel reference processing if the number of parallel threads - to use is larger than one. - The option is available only when the throughput or G1 garbage collector is used - (`-XX:+UseParallelGC` or `-XX:+UseG1GC`). Other collectors employing multiple - threads always perform reference processing in parallel. - ## Obsolete Java Options These `java` options are still accepted but ignored, and a warning is issued @@ -3017,6 +3009,18 @@ when they're used. 396](https://openjdk.org/jeps/396) and made obsolete in JDK 17 by [JEP 403](https://openjdk.org/jeps/403). +## Removed Java Options + +These `java` options have been removed in JDK @@VERSION_SPECIFICATION@@ and using them results in an error of: + +> `Unrecognized VM option` *option-name* + +[`-XX:+AggressiveHeap`]{#-XX__AggressiveHeap} +: Enabled Java heap optimization. This set various parameters to be + optimal for long-running jobs with intensive memory allocation, based on + the configuration of the computer (RAM and CPU). By default, the option + was disabled and the heap sizes configured less aggressively. + [`-XX:+NeverActAsServerClassMachine`]{#-XX__NeverActAsServerClassMachine} : Enabled the "Client VM emulation" mode, which used only the C1 JIT compiler, a 32Mb CodeCache, and the Serial GC. The maximum amount of memory that the @@ -3037,18 +3041,18 @@ when they're used. -XX:{+|-}UseJVMCICompiler ``` -[`-XX:+AggressiveHeap`]{#-XX__AggressiveHeap} -: Enabled Java heap optimization. This set various parameters to be - optimal for long-running jobs with intensive memory allocation, based on - the configuration of the computer (RAM and CPU). By default, the option - was disabled and the heap sizes configured less aggressively. - -## Removed Java Options - -No documented java options have been removed in JDK @@VERSION_SPECIFICATION@@. +[`-XX:+ParallelRefProcEnabled`]{#-XX__ParallelRefProcEnabled} +: Enables parallel reference processing. By default, collectors employing multiple + threads perform parallel reference processing if the number of parallel threads + to use is larger than one. + The option is available only when the throughput or G1 garbage collector is used + (`-XX:+UseParallelGC` or `-XX:+UseG1GC`). Other collectors employing multiple + threads always perform reference processing in parallel. For the lists and descriptions of options removed in previous releases see the *Removed Java Options* section in: +- [The `java` Command, Release 27](https://docs.oracle.com/en/java/javase/27/docs/specs/man/java.html) + - [The `java` Command, Release 26](https://docs.oracle.com/en/java/javase/26/docs/specs/man/java.html) - [The `java` Command, Release 25](https://docs.oracle.com/en/java/javase/25/docs/specs/man/java.html) From ac85fddbbc89189dc7dd36991bea82157db699f7 Mon Sep 17 00:00:00 2001 From: Richard Reingruber Date: Tue, 9 Jun 2026 05:14:05 +0000 Subject: [PATCH 04/18] 8385166: PPC: C2: c_return_value and return_value should not set 2nd OptoRegPair for Op_RegI Reviewed-by: mdoerr, dbriemann --- src/hotspot/cpu/ppc/ppc.ad | 42 +++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/src/hotspot/cpu/ppc/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad index 7360ed604f1..ea1768c6afd 100644 --- a/src/hotspot/cpu/ppc/ppc.ad +++ b/src/hotspot/cpu/ppc/ppc.ad @@ -3475,30 +3475,34 @@ frame %{ // 4 what apparently works and saves us some spills. return_addr(STACK 4); - // Location of native (C/C++) and interpreter return values. This - // is specified to be the same as Java. In the 32-bit VM, long - // values are actually returned from native calls in O0:O1 and - // returned to the interpreter in I0:I1. The copying to and from - // the register pairs is done by the appropriate call and epilog - // opcodes. This simplifies the register allocator. - c_return_value %{ - assert((ideal_reg >= Op_RegI && ideal_reg <= Op_RegL) || - (ideal_reg == Op_RegN && CompressedOops::base() == nullptr && CompressedOops::shift() == 0), - "only return normal values"); - // enum names from opcodes.hpp: Op_Node Op_Set Op_RegN Op_RegI Op_RegP Op_RegF Op_RegD Op_RegL - static int typeToRegLo[Op_RegL+1] = { 0, 0, R3_num, R3_num, R3_num, F1_num, F1_num, R3_num }; - static int typeToRegHi[Op_RegL+1] = { 0, 0, OptoReg::Bad, R3_H_num, R3_H_num, OptoReg::Bad, F1_H_num, R3_H_num }; - return OptoRegPair(typeToRegHi[ideal_reg], typeToRegLo[ideal_reg]); - %} - // Location of compiled Java return values. Same as C return_value %{ assert((ideal_reg >= Op_RegI && ideal_reg <= Op_RegL) || (ideal_reg == Op_RegN && CompressedOops::base() == nullptr && CompressedOops::shift() == 0), "only return normal values"); - // enum names from opcodes.hpp: Op_Node Op_Set Op_RegN Op_RegI Op_RegP Op_RegF Op_RegD Op_RegL - static int typeToRegLo[Op_RegL+1] = { 0, 0, R3_num, R3_num, R3_num, F1_num, F1_num, R3_num }; - static int typeToRegHi[Op_RegL+1] = { 0, 0, OptoReg::Bad, R3_H_num, R3_H_num, OptoReg::Bad, F1_H_num, R3_H_num }; + // enum names from opcodes.hpp + static int typeToRegLo[Op_RegL+1] = { + 0, // Op_Node + 0, // Op_Set + R3_num, // Op_RegN + R3_num, // Op_RegI + R3_num, // Op_RegP + F1_num, // Op_RegF + F1_num, // Op_RegD + R3_num, // Op_RegL + }; + + static int typeToRegHi[Op_RegL+1] = { + 0, // Op_Node + 0, // Op_Set + OptoReg::Bad, // Op_RegN + OptoReg::Bad, // Op_RegI + R3_H_num, // Op_RegP + OptoReg::Bad, // Op_RegF + F1_H_num, // Op_RegD + R3_H_num // Op_RegL + }; + return OptoRegPair(typeToRegHi[ideal_reg], typeToRegLo[ideal_reg]); %} %} From 7a7ee23168584b5ff80c3cb11360b738089f11c3 Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Tue, 9 Jun 2026 07:25:12 +0000 Subject: [PATCH 05/18] 8385454: Provide more NUMA related information in hsinfo/hserr files Reviewed-by: jsikstro, dbriemann --- src/hotspot/os/linux/os_linux.cpp | 95 +++++++++++++++++++++++++++++++ src/hotspot/os/linux/os_linux.hpp | 1 + 2 files changed, 96 insertions(+) diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index ba48f2b4efc..ad1f384fa32 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -2183,6 +2183,10 @@ void os::print_os_info(outputStream* st) { st->cr(); } + if (os::Linux::print_numa_info(st)) { + st->cr(); + } + VM_Version::print_platform_virtualization_info(st); os::Linux::print_steal_info(st); @@ -2622,6 +2626,97 @@ bool os::Linux::print_container_info(outputStream* st) { return true; } +#define SYS_DEVICES_NODE "/sys/devices/system/node" + +static size_t read_sysfs_file(const char* path, char* buf, size_t sz) { + FILE* f = os::fopen(path, "r"); + if (f == nullptr) return 0; + size_t n = fread(buf, 1, sz - 1, f); + fclose(f); + buf[n] = '\0'; + while (n > 0 && (buf[n-1] == '\n' || buf[n-1] == '\r')) buf[--n] = '\0'; + return n; +} + +static void print_numa_memory_info(outputStream* st, int node) { + char path[256]; + char line[256]; + long long mem_total = -1; + long long mem_free = -1; + os::snprintf_checked(path, sizeof(path), SYS_DEVICES_NODE "/node%d/meminfo", node); + FILE* f = os::fopen(path, "r"); + if (f == nullptr) { + return; + } + + while (fgets(line, sizeof(line), f) != nullptr) { + long long mval; + if (sscanf(line, "Node %*d MemTotal: %lld kB", &mval) == 1) mem_total = mval; + if (sscanf(line, "Node %*d MemFree: %lld kB", &mval) == 1) mem_free = mval; + } + fclose(f); + + if (mem_total >= 0) { st->print_cr("mem size: %lld kB", mem_total); } + if (mem_free >= 0) { st->print_cr("mem free: %lld kB", mem_free); } +} + +static void print_numa_cpu_list(outputStream* st, int node) { + char path[256]; + char buf[1024]; + os::snprintf_checked(path, sizeof(path), SYS_DEVICES_NODE "/node%d/cpulist", node); + if (read_sysfs_file(path, buf, sizeof(buf)) > 0) { + st->print_cr("cpus: %s", buf); + } else { + st->print_cr("cpus: (unavailable)"); + } +} + +bool os::Linux::print_numa_info(outputStream* st) { + if (!UseNUMA) { + // If NUMA optimizations are not enabled we don't print anything + return false; + } + + char buf[1024]; + if (read_sysfs_file("/sys/devices/system/node/online", buf, sizeof(buf)) > 0) { + st->print_cr("NUMA nodes online: %s", buf); + } else { + return false; + } + + bool first = true; + int node_count = 0; + + if (nindex_to_node() == nullptr) { + return false; + } + + for (int node: *nindex_to_node()) { + char nodepath[256]; + os::snprintf_checked(nodepath, sizeof(nodepath), SYS_DEVICES_NODE "/node%d", node); + DIR* currd = os::opendir(nodepath); + if (currd == nullptr) continue; + if (first) { + st->cr(); + first = false; + } + os::closedir(currd); + + st->print_cr("NUMA node %d", node); + StreamIndentor si(st); + print_numa_cpu_list(st, node); + print_numa_memory_info(st, node); + node_count++; + } + + if (node_count == 0) { + return false; + } + + st->print_cr("Total NUMA node count: %d", node_count); + return true; +} + void os::Linux::print_steal_info(outputStream* st) { if (has_initial_tick_info) { CPUPerfTicks pticks; diff --git a/src/hotspot/os/linux/os_linux.hpp b/src/hotspot/os/linux/os_linux.hpp index 41b5afbf5c3..51a10be1e5d 100644 --- a/src/hotspot/os/linux/os_linux.hpp +++ b/src/hotspot/os/linux/os_linux.hpp @@ -77,6 +77,7 @@ class os::Linux { static void print_proc_sys_info(outputStream* st); static bool print_ld_preload_file(outputStream* st); static void print_uptime_info(outputStream* st); + static bool print_numa_info(outputStream* st); public: struct CPUPerfTicks { From 8556794f6ef74413822aab6ccfa309194d6a1f4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20H=C3=A4ssig?= Date: Tue, 9 Jun 2026 09:06:34 +0000 Subject: [PATCH 06/18] 8385950: Git: add ignore revisions file Reviewed-by: erikj --- .git-blame-ignore-revs | 184 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 .git-blame-ignore-revs diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 00000000000..ee91f5d33e2 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,184 @@ +# git blame ignore revs file +# +# The list of revisions below will be ignored by git-blame (1) if this file gets +# passed via the --ignore-revs-file command line option or is configured using +# the blame.ignoreRevsFile key. +# +# Only add commits that obviously do not change semantics, e.g. mechanical refactorings +# or formatting. Always add the commit message as a comment above the revision +# to keep the file readable. + +# 8299973: Replace NULL with nullptr in share/utilities/ +1084fd24eb118d4131538c2a3ead714db7d0357b + +# 8299974: Replace NULL with nullptr in share/adlc/ +62537d200f01d58ff1c236f31f71c5839316db9e + +# 8300081: Replace NULL with nullptr in share/asm/ +9d5bab11f08a992803399f422d75b17f8607df72 + +# 8300086: Replace NULL with nullptr in share/c1/ +90d5041b6a055d6266140ffea2aa9a3b08b32209 + +# 8300087: Replace NULL with nullptr in share/cds/ +eca64795be63c599a637ce2a7f740b2d0a1ec9bc + +# 8300222: Replace NULL with nullptr in share/logging +bd5ca953058704087da4bc5796b3ce28ce2a8f78 + +# 8300240: Replace NULL with nullptr in share/ci/ +f52d35c84b7333809156d201c866793854143888 + +# 8300241: Replace NULL with nullptr in share/classfile/ +49ff52087be8b95cbf369518281312ecc9d83618 + +# 8300242: Replace NULL with nullptr in share/code/ +cfe57466ddecb93b528478d0b053b089dd1ed285 + +# 8300243: Replace NULL with nullptr in share/compiler/ +fcbf9d052efd16821750fb20813f8030ee828472 + +# 8300244: Replace NULL with nullptr in share/interpreter/ +a5d8e12872d9de399fa97b33896635d101b71372 + +# 8300245: Replace NULL with nullptr in share/jfr/ +cc396895e5a1dac49f4e341ce91c04b8c092d0af + +# 8300651: Replace NULL with nullptr in share/runtime/ +71107f4648d8f31a7bcc0aa5202ef46230df583f + +# 8301068: Replace NULL with nullptr in share/jvmci/ +90ec19efeda90f13a918b4481fe6ee552ab2af66 + +# 8301069: Replace NULL with nullptr in share/libadt/ +b0376a5f4421fb58c0feeddfce2c2083314e400c + +# 8301070: Replace NULL with nullptr in share/memory/ +d98a323a8b972c17a066c597a81b164681ad5589 + +# 8301072: Replace NULL with nullptr in share/oops/ +c8ace482edead720c865cf996729a316025d937e + +# 8301074: Replace NULL with nullptr in share/opto/ +5726d31e56530bbe7dee61ae04b126e20cb3611d + +# 8301076: Replace NULL with nullptr in share/prims/ +b76a52f2104b63e84e5d09f47ce01dd0cb3935d7 + +# 8301077: Replace NULL with nullptr in share/services/ +5c1ec82656323872c4628026662fe5b62e7a61e3 + +# 8301178: Replace NULL with nullptr in share/gc/epsilon/ +b77abc6a0daed0e01a9003d42493320376dc98bc + +# 8301179: Replace NULL with nullptr in share/gc/serial/ +107e184d59c0bbed6441a3c1a9bfd4527da3bce5 + +# 8301180: Replace NULL with nullptr in share/gc/parallel/ +3758487fda61b27e7e684413793ed28c0b9e64d3 + +# 8301223: Replace NULL with nullptr in share/gc/g1/ +75a4edca6b9fa6b3e66b564aeb4d7ca8acf02491 + +# 8301225: Replace NULL with nullptr in share/gc/shenandoah/ +0c9658446d111ec944f06b7a8a4e3ae7bf53ee8d + +# 8301477: Replace NULL with nullptr in os/aix +43288bbd684abfcefdf385ed1e0307070399ccbf + +# 8301478: Replace NULL with nullptr in os/bsd +716f1df609e7f0aa7b3b9383d23dde5c71017d02 + +# 8301479: Replace NULL with nullptr in os/linux +ac9e046748a9bb6ee065dc473d82135ce36043b7 + +# 8301480: Replace NULL with nullptr in os/posix +4539899c55c77771b951d005c17550ef9ac94819 + +# 8301481: Replace NULL with nullptr in os/windows +c91cd2814baa8dee2af8af0fecf9185d4a0a44cf + +# 8301493: Replace NULL with nullptr in cpu/aarch64 +948f3b3c24709eca3aa6c3f0db6adb9226d6f9ac + +# 8301494: Replace NULL with nullptr in cpu/arm +c4ffe4bf6369d5b271aa8689b8648f3fe8dcabed + +# 8301495: Replace NULL with nullptr in cpu/ppc +0826ceee65ab83f643a77716f8f12d0060369923 + +# 8301496: Replace NULL with nullptr in cpu/riscv +d2ce04bb101002abfdb7c8adb3fa8ea267903c36 + +# 8301497: Replace NULL with nullptr in cpu/s390 +54f7b6ca34986cc26c5b91c6724b9a1754c94391 + +# 8301498: Replace NULL with nullptr in cpu/x86 +4154a980ca28c1ae56db26e3dce64c07c225de12 + +# 8301499: Replace NULL with nullptr in cpu/zero +4e327db1d127c652ef39e31c164e36ae429a0065 + +# 8301500: Replace NULL with nullptr in os_cpu/aix_ppc +c8307e37fdf4453cade84efc113d93dd14333fd0 + +# 8301501: Replace NULL with nullptr in os_cpu/bsd_aarch64 +218223e4a31d485935655cb3f186a752defd8fa8 + +# 8301502: Replace NULL with nullptr in os_cpu/bsd_x86 +6daff6b26946748360d59a12e9069a08ab5ca06d + +# 8301503: Replace NULL with nullptr in os_cpu/bsd_zero +8cc399b672c6ce08037685b3a3a2db3c53a87b50 + +# 8301504: Replace NULL with nullptr in os_cpu/linux_aarch64 +13fcd602d37eb0095f169255128588b872639571 + +# 8301505: Replace NULL with nullptr in os_cpu/linux_arm +b81f0ff43ac8d1431f2f5dccb7499a3a1503823d + +# 8301506: Replace NULL with nullptr in os_cpu/linux_ppc +b1e96989b693aadea082a01576e25f85ed28ff0d + +# 8301507: Replace NULL with nullptr in os_cpu/linux_riscv +182d1b2fb7034b6e9177dc360cbea43d548c3ff0 + +# 8301508: Replace NULL with nullptr in os_cpu/linux_s390 +d097b5e6285e1a59632211e006592fedf2047c09 + +# 8301509: Replace NULL with nullptr in os_cpu/linux_x86 +5d1f71daf06870810c9ca24e911d6191cc4f3006 + +# 8301511: Replace NULL with nullptr in os_cpu/linux_zero +42a286a15862d9a05ea3477a9eeab46e7b33e599 + +# 8301512: Replace NULL with nullptr in os_cpu/windows_aarch64 +ad79e49141f063a61090eda69d96dc580db88949 + +# 8301513: Replace NULL with nullptr in os_cpu/windows_x86 +c109dae48c61c6fbeacadf59d509d37d2c4d2bb8 + +# 8308092: Replace NULL with nullptr in gc/x +599fa774b875da971d66f79e5e43ede2b5ce18aa + +# 8309044: Replace NULL with nullptr, final sweep of hotspot code +4f16161607edbf69f423ced1d3c24f7af058d46b + +# 8324286: Fix backsliding on use of nullptr instead of NULL +bcb340da091e3287da8d2ecfcd017ebcc6613cae + +# 8324678: Replace NULL with nullptr in HotSpot gtests +c1281e6b45ed167df69d29a6039d81854c145ae6 + +# 8324679: Replace NULL with nullptr in HotSpot .ad files +b3ecd55601d483359819d02e70789bbd412b13da + +# 8324680: Replace NULL with nullptr in JVMTI generated code +267780bf0adf4bfd831fbc04347e297fa8f3bb01 + +# 8324681: Replace NULL with nullptr in HotSpot jtreg test native code files +a6bdee48f39993128d8095d40ab417f0102af0f4 + +# 8324799: Use correct extension for C++ test headers +998d0baab0fd051c38d9fd6021628eb863b80554 + From f4b46d86dd690a47b894ce9a186d5c98149c3382 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Tue, 9 Jun 2026 09:09:21 +0000 Subject: [PATCH 07/18] 8385989: Remove mention of obsoleted/removed ParallelRefProcEnabled in documentation Reviewed-by: aboldtch, jsikstro --- src/hotspot/share/gc/shared/gc_globals.hpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/hotspot/share/gc/shared/gc_globals.hpp b/src/hotspot/share/gc/shared/gc_globals.hpp index 1ff6fd493a7..14bc320e32c 100644 --- a/src/hotspot/share/gc/shared/gc_globals.hpp +++ b/src/hotspot/share/gc/shared/gc_globals.hpp @@ -199,10 +199,9 @@ range(1, (INT_MAX - 1)) \ \ product(size_t, ReferencesPerThread, 1000, EXPERIMENTAL, \ - "Ergonomically start one thread for this amount of " \ - "references for reference processing if " \ - "ParallelRefProcEnabled is true. Specify 0 to disable and " \ - "use all threads.") \ + "Ergonomically start one thread for this amount of references " \ + "for reference processing for parallel stop-the-world garbage " \ + "collectors. Specify 0 to force use of all available threads.") \ \ product(uint, InitiatingHeapOccupancyPercent, 45, \ "The percent occupancy (IHOP) of the current old generation " \ From ff2b7b3f9d57be6f869759f3cda3e3debb05d047 Mon Sep 17 00:00:00 2001 From: Amit Kumar Date: Tue, 9 Jun 2026 09:12:01 +0000 Subject: [PATCH 08/18] 8386150: VtablesTest.java fails when main thread is a Virtual Thread Reviewed-by: syan, shade --- test/hotspot/jtreg/runtime/logging/VtablesTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/hotspot/jtreg/runtime/logging/VtablesTest.java b/test/hotspot/jtreg/runtime/logging/VtablesTest.java index a07fe895173..c87c274d31d 100644 --- a/test/hotspot/jtreg/runtime/logging/VtablesTest.java +++ b/test/hotspot/jtreg/runtime/logging/VtablesTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -55,7 +55,7 @@ public class VtablesTest { output.shouldContain("NOT overriding with p2.D.nooverride()V"); output.shouldHaveExitValue(0); - pb = ProcessTools.createLimitedTestJavaProcessBuilder("-Xlog:vtables=trace", "p1/C"); + pb = ProcessTools.createLimitedTestJavaProcessBuilder("-Xlog:vtables=trace", "p1.C"); output = new OutputAnalyzer(pb.start()); output.shouldContain("transitive overriding superclass "); output.shouldHaveExitValue(0); From b6fb712b6fcb1095c162ba15bf519045a8c451ae Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Tue, 9 Jun 2026 12:56:01 +0000 Subject: [PATCH 09/18] 8385839: JMX config file correction Reviewed-by: sspitsyn --- .../share/conf/jmxremote.password.template | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/jdk.management.agent/share/conf/jmxremote.password.template b/src/jdk.management.agent/share/conf/jmxremote.password.template index c98a0ad253a..0b0607497de 100644 --- a/src/jdk.management.agent/share/conf/jmxremote.password.template +++ b/src/jdk.management.agent/share/conf/jmxremote.password.template @@ -55,8 +55,6 @@ # * com.sun.management.jmxremote.password.toHashes property is set to true in # management.properties file # * the password file is writable -# * the system security policy allows writing into the password file, if a -# security manager is configured # # In order to change the password for a role, replace the hashed password entry # with a new clear text password or a new hashed password. If the new password @@ -110,6 +108,6 @@ # below entries with clear passwords overwritten by their respective # SHA3-512 hash # -# monitorRole trilby APzBTt34rV2l+OMbuvbnOQ4si8UZmfRCVbIY1+fAofV5CkQzXS/FDMGteQQk/R3q1wtt104qImzJEA7gCwl6dw== 4EeTdSJ7X6Imu0Mb+dWqIns7a7QPIBoM3NB/XlpMQSPSicE7PnlALVWn2pBY3Q3pGDHyAb32Hd8GUToQbUhAjA== SHA3-512 +# monitorRole APzBTt34rV2l+OMbuvbnOQ4si8UZmfRCVbIY1+fAofV5CkQzXS/FDMGteQQk/R3q1wtt104qImzJEA7gCwl6dw== 4EeTdSJ7X6Imu0Mb+dWqIns7a7QPIBoM3NB/XlpMQSPSicE7PnlALVWn2pBY3Q3pGDHyAb32Hd8GUToQbUhAjA== SHA3-512 # controlRole roHEJSbRqSSTII4Z4+NOCV2OJaZVQ/dw153Fy2u4ILDP9XiZ426GwzCzc3RtpoqNMwqYIcfdd74xWXSMrWtGaA== w9qDsekgKn0WOVJycDyU0kLBa081zbStcCjUAVEqlfon5Sgx7XHtaodbmzpLegA1jT7Ag36T0zHaEWRHJe2fdA== SHA3-512 -# \ No newline at end of file +# From a529e45ad3958578275df0a6ec175d45d18ada2f Mon Sep 17 00:00:00 2001 From: Alexey Ivanov Date: Tue, 9 Jun 2026 16:00:42 +0000 Subject: [PATCH 10/18] 8291470: Description change for mouseMoved method in java.awt.event.MouseMotionAdapter Reviewed-by: azvegint, prr, serb --- .../java/awt/event/MouseMotionAdapter.java | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/src/java.desktop/share/classes/java/awt/event/MouseMotionAdapter.java b/src/java.desktop/share/classes/java/awt/event/MouseMotionAdapter.java index 4c284bf29ba..6bec617b5ae 100644 --- a/src/java.desktop/share/classes/java/awt/event/MouseMotionAdapter.java +++ b/src/java.desktop/share/classes/java/awt/event/MouseMotionAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -32,13 +32,13 @@ package java.awt.event; *

* Mouse motion events occur when a mouse is moved or dragged. * (Many such events will be generated in a normal program. - * To track clicks and other mouse events, use the MouseAdapter.) + * To track clicks and other mouse events, use the {@link MouseAdapter}.) *

* Extend this class to create a {@code MouseEvent} listener * and override the methods for the events of interest. (If you implement the * {@code MouseMotionListener} interface, you have to define all of * the methods in it. This abstract class defines null methods for them - * all, so you can only have to define methods for events you care about.) + * all, so you have to define only methods for events you care about.) *

* Create a listener object using the extended class and then register it with * a component using the component's {@code addMouseMotionListener} @@ -61,17 +61,14 @@ public abstract class MouseMotionAdapter implements MouseMotionListener { protected MouseMotionAdapter() {} /** - * Invoked when a mouse button is pressed on a component and then - * dragged. Mouse drag events will continue to be delivered to - * the component where the first originated until the mouse button is - * released (regardless of whether the mouse position is within the - * bounds of the component). + * {@inheritDoc} */ + @Override public void mouseDragged(MouseEvent e) {} /** - * Invoked when the mouse button has been moved on a component - * (with no buttons no down). + * {@inheritDoc} */ + @Override public void mouseMoved(MouseEvent e) {} } From 7f62474fcb63392c61239c0a54ddea70002832ac Mon Sep 17 00:00:00 2001 From: Justin Lu Date: Tue, 9 Jun 2026 16:28:45 +0000 Subject: [PATCH 11/18] 8386200: ListFormat incorrectly escapes single quotes Reviewed-by: naoto --- .../share/classes/java/text/ListFormat.java | 29 +++++++++++++++---- .../Format/ListFormat/TestListFormat.java | 14 ++++++++- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/src/java.base/share/classes/java/text/ListFormat.java b/src/java.base/share/classes/java/text/ListFormat.java index 29e58ea717c..c610ace64d6 100644 --- a/src/java.base/share/classes/java/text/ListFormat.java +++ b/src/java.base/share/classes/java/text/ListFormat.java @@ -498,15 +498,18 @@ public final class ListFormat extends Format { midIndex += mbLength; } } - parsed = new MessageFormat(createMessageFormatString(count), locale).parseObject(source, parsePos); + parsed = new MessageFormat(listToMessageFormatPattern(createMessageFormatString(count)), + locale).parseObject(source, parsePos); } } if (parsed == null) { // now try exact number patterns - parsed = new MessageFormat(patterns[TWO], locale).parseObject(source, parsePos); + parsed = new MessageFormat(listToMessageFormatPattern(patterns[TWO]), + locale).parseObject(source, parsePos); if (parsed == null) { - parsed = new MessageFormat(patterns[THREE], locale).parseObject(source, parsePos); + parsed = new MessageFormat(listToMessageFormatPattern(patterns[THREE]), + locale).parseObject(source, parsePos); } } @@ -584,9 +587,9 @@ public final class ListFormat extends Format { var len = input.length; return switch (len) { case 0 -> throw new IllegalArgumentException("There should at least be one input string"); - case 1 -> new MessageFormat("{0}", locale); - case 2, 3 -> new MessageFormat(patterns[len + 1], locale); - default -> new MessageFormat(createMessageFormatString(len), locale); + case 1 -> new MessageFormat(listToMessageFormatPattern("{0}"), locale); + case 2, 3 -> new MessageFormat(listToMessageFormatPattern(patterns[len + 1]), locale); + default -> new MessageFormat(listToMessageFormatPattern(createMessageFormatString(len)), locale); }; } @@ -742,4 +745,18 @@ public final class ListFormat extends Format { return prefixPos < suffixPos ? new int[] {prefixPos, suffixPos + suffix.length()} : null; } + + /** + * {@return the MessageFormat pattern corresponding to the passed ListFormat pattern} + * + * Single quotes must be escaped so they are interpreted as literal text + * as opposed to escaping delimiters when passed to MessageFormat. Everything + * else remains the same; ListFormat already handles other validation on its own. + * + * @param pattern list pattern to use + */ + private static String listToMessageFormatPattern(String pattern) { + return pattern.indexOf('\'') < 0 ? pattern : + pattern.replace("'", "''"); + } } diff --git a/test/jdk/java/text/Format/ListFormat/TestListFormat.java b/test/jdk/java/text/Format/ListFormat/TestListFormat.java index 68da9ce5fda..e85e98b6cf6 100644 --- a/test/jdk/java/text/Format/ListFormat/TestListFormat.java +++ b/test/jdk/java/text/Format/ListFormat/TestListFormat.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8041488 8316974 8318569 8306116 8385736 8385834 + * @bug 8041488 8316974 8318569 8306116 8385736 8385834 8386200 * @summary Tests for ListFormat class * @run junit TestListFormat */ @@ -74,6 +74,14 @@ public class TestListFormat { "", "", }; + // Ensures MessageFormat single quotes in custom patterns are treated as literals. + private static final String[] CUSTOM_PATTERNS_SINGLE_QUOTE = { + "' {0} ' {1}", + "{0} '' {1}", + "{0} ''' {1} '''", + "", + "", + }; private static final String[] CUSTOM_PATTERNS_IAE_START = { "{0}", "{0} mid {1}", @@ -142,6 +150,10 @@ public class TestListFormat { arguments(CUSTOM_PATTERNS_METACHAR, SAMPLE2, ". foo | bar ["), arguments(CUSTOM_PATTERNS_METACHAR, SAMPLE3, ". foo * bar | baz ["), arguments(CUSTOM_PATTERNS_METACHAR, SAMPLE4, ". foo * bar + baz | qux ["), + arguments(CUSTOM_PATTERNS_SINGLE_QUOTE, SAMPLE1, "foo"), + arguments(CUSTOM_PATTERNS_SINGLE_QUOTE, SAMPLE2, "' foo ''' bar '''"), + arguments(CUSTOM_PATTERNS_SINGLE_QUOTE, SAMPLE3, "' foo ' bar ''' baz '''"), + arguments(CUSTOM_PATTERNS_SINGLE_QUOTE, SAMPLE4, "' foo ' bar '' baz ''' qux '''") }; } From 543c21dde67c1014605ab314bb2567184d48934f Mon Sep 17 00:00:00 2001 From: Artur Barashev Date: Tue, 9 Jun 2026 17:35:26 +0000 Subject: [PATCH 12/18] 8386203: Use CRC32C checksum instead of Adler32 for stateless session ticket Reviewed-by: mullan, ascarpino --- .../share/classes/sun/security/ssl/SSLSessionImpl.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java b/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java index af0b8909d30..45882a79fd7 100644 --- a/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java +++ b/src/java.base/share/classes/sun/security/ssl/SSLSessionImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -40,7 +40,7 @@ import java.util.Queue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.locks.ReentrantLock; -import java.util.zip.Adler32; +import java.util.zip.CRC32C; import javax.crypto.KDF; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; @@ -610,9 +610,9 @@ final class SSLSessionImpl extends ExtendedSSLSession { } private static int getChecksum(byte[] input) { - Adler32 adler32 = new Adler32(); - adler32.update(input); - return (int) adler32.getValue(); + CRC32C crc32c = new CRC32C(); + crc32c.update(input); + return (int) crc32c.getValue(); } void setMasterSecret(SecretKey secret) { From ced72988629662e1bedac633503845aebb7aed9b Mon Sep 17 00:00:00 2001 From: Xiaolong Peng Date: Tue, 9 Jun 2026 19:22:56 +0000 Subject: [PATCH 13/18] 8385961: Shenandoah: incorrect assert ordering in ShenandoahFreeSet::allocate_contiguous non-humongous path Reviewed-by: shade, wkemper --- src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp index 4c474f2f86c..6563ffb6359 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp @@ -1745,8 +1745,8 @@ HeapWord* ShenandoahFreeSet::allocate_contiguous(ShenandoahAllocRequest& req, bo for (idx_t i = beg; i <= end; i++) { ShenandoahHeapRegion* r = _heap->get_region(i); assert(i == beg || _heap->get_region(i - 1)->index() + 1 == r->index(), "Should be contiguous"); - assert(r->is_empty(), "Should be empty"); r->try_recycle_under_lock(); + assert(r->is_empty(), "Should be empty"); r->set_affiliation(req.affiliation()); r->make_regular_allocation(req.affiliation()); if ((i == end) && (used_words_in_last_region > 0)) { From 6c7fe6fd2045f13fce28139e8e6c5c1a9f6fa7d3 Mon Sep 17 00:00:00 2001 From: Jasmine Karthikeyan Date: Tue, 9 Jun 2026 23:00:22 +0000 Subject: [PATCH 14/18] 8349563: Improve AbsNode::Value() for integer types Reviewed-by: epeter, mchevalier, qamai --- src/hotspot/share/opto/subnode.cpp | 37 +- src/hotspot/share/opto/type.cpp | 12 + src/hotspot/share/opto/type.hpp | 4 + .../jtreg/compiler/c2/irTests/TestIRAbs.java | 567 +++++++++++++++++- 4 files changed, 605 insertions(+), 15 deletions(-) diff --git a/src/hotspot/share/opto/subnode.cpp b/src/hotspot/share/opto/subnode.cpp index 014f41f82cc..39d5f0be90c 100644 --- a/src/hotspot/share/opto/subnode.cpp +++ b/src/hotspot/share/opto/subnode.cpp @@ -1921,6 +1921,31 @@ bool BoolNode::is_counted_loop_exit_test() { return false; } +template +static const IntegerType* integral_abs_value(const IntegerType* t) { + typedef typename IntegerType::NativeUType NativeUType; + + // Find the absolute value of a type, resulting in a range that fits inside the unsigned range [0, signed_max+1]. + // The possible values of a TypeInteger is described with the following range in the signed domain: + // smin----------lo=======uhi--------0--------ulo===========hi----------smax + + // To find the absolute value of the range, we find the closer (min) value of uhi and ulo to 0, and the further (max) + // value of lo and hi from 0. In the unsigned domain, the resulting range looks like this: + // 0-----------min(|ulo|,|uhi|)================max(|lo|,|hi|)-----------umax + + // When the input range's hi and lo are both positive or negative, lo == ulo and hi == uhi: + // smin------------------------------0-------lo===========hi------------smax (Positive) + // smin--------lo===========hi-------0----------------------------------smax (Negative) + + // For these ranges, the result in the unsigned domain is simply [min(|lo|, |hi|), max(|lo|, |hi|)]: + // 0-----------min(|lo|,|hi|)==================max(|lo|,|hi|)-----------umax + + NativeUType umin = MIN2(g_uabs(t->_ulo), g_uabs(t->_uhi)); + NativeUType umax = MAX2(g_uabs(t->_lo), g_uabs(t->_hi)); + + return IntegerType::make_unsigned(umin, umax, t->_widen); +} + //============================================================================= //------------------------------Value------------------------------------------ const Type* AbsNode::Value(PhaseGVN* phase) const { @@ -1930,17 +1955,13 @@ const Type* AbsNode::Value(PhaseGVN* phase) const { switch (t1->base()) { case Type::Int: { const TypeInt* ti = t1->is_int(); - if (ti->is_con()) { - return TypeInt::make(g_uabs(ti->get_con())); - } - break; + + return integral_abs_value(ti); } case Type::Long: { const TypeLong* tl = t1->is_long(); - if (tl->is_con()) { - return TypeLong::make(g_uabs(tl->get_con())); - } - break; + + return integral_abs_value(tl); } case Type::FloatCon: return TypeF::make(abs(t1->getf())); diff --git a/src/hotspot/share/opto/type.cpp b/src/hotspot/share/opto/type.cpp index fcdf9b09fc3..a1e213319b7 100644 --- a/src/hotspot/share/opto/type.cpp +++ b/src/hotspot/share/opto/type.cpp @@ -1801,6 +1801,12 @@ const TypeInt* TypeInt::make(jint lo, jint hi, int widen) { return make_or_top(TypeIntPrototype{{lo, hi}, {0, max_juint}, {0, 0}}, widen)->is_int(); } +const TypeInt* TypeInt::make_unsigned(juint ulo, juint uhi, int widen) { + assert(ulo <= uhi, "must be legal bounds"); + // By creating the TypeInt with the full signed range and the given unsigned range, the signed bounds are inferred from the unsigned bounds. + return make_or_top(TypeIntPrototype{{min_jint, max_jint}, {ulo, uhi}, {0, 0}}, widen)->is_int(); +} + const Type* TypeInt::make_or_top(const TypeIntPrototype& t, int widen) { return make_or_top(t, widen, false); } @@ -1936,6 +1942,12 @@ const TypeLong* TypeLong::make(jlong lo, jlong hi, int widen) { return make_or_top(TypeIntPrototype{{lo, hi}, {0, max_julong}, {0, 0}}, widen)->is_long(); } +const TypeLong* TypeLong::make_unsigned(julong ulo, julong uhi, int widen) { + assert(ulo <= uhi, "must be legal bounds"); + // By creating the TypeLong with the full signed range and the given unsigned range, the signed bounds are inferred from the unsigned bounds. + return make_or_top(TypeIntPrototype{{min_jlong, max_jlong}, {ulo, uhi}, {0, 0}}, widen)->is_long(); +} + const Type* TypeLong::make_or_top(const TypeIntPrototype& t, int widen) { return make_or_top(t, widen, false); } diff --git a/src/hotspot/share/opto/type.hpp b/src/hotspot/share/opto/type.hpp index 6eaa497e86d..06201113311 100644 --- a/src/hotspot/share/opto/type.hpp +++ b/src/hotspot/share/opto/type.hpp @@ -782,6 +782,7 @@ protected: public: typedef jint NativeType; + typedef juint NativeUType; virtual bool eq(const Type* t) const; virtual uint hash() const; // Type specific hashing virtual bool singleton(void) const; // TRUE if type is a singleton @@ -795,6 +796,7 @@ public: static const TypeInt* make(jint con); // must always specify w static const TypeInt* make(jint lo, jint hi, int widen); + static const TypeInt* make_unsigned(juint ulo, juint uhi, int widen); static const Type* make_or_top(const TypeIntPrototype& t, int widen); static const TypeInt* make(const TypeIntPrototype& t, int widen) { return make_or_top(t, widen)->is_int(); } static const TypeInt* make(const TypeIntMirror& t, int widen) { @@ -871,6 +873,7 @@ protected: virtual const Type* filter_helper(const Type* kills, bool include_speculative) const; public: typedef jlong NativeType; + typedef julong NativeUType; virtual bool eq( const Type *t ) const; virtual uint hash() const; // Type specific hashing virtual bool singleton(void) const; // TRUE if type is a singleton @@ -885,6 +888,7 @@ public: static const TypeLong* make(jlong con); // must always specify w static const TypeLong* make(jlong lo, jlong hi, int widen); + static const TypeLong* make_unsigned(julong ulo, julong uhi, int widen); static const Type* make_or_top(const TypeIntPrototype& t, int widen); static const TypeLong* make(const TypeIntPrototype& t, int widen) { return make_or_top(t, widen)->is_long(); } static const TypeLong* make(const TypeIntMirror& t, int widen) { diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestIRAbs.java b/test/hotspot/jtreg/compiler/c2/irTests/TestIRAbs.java index a40c9eab12f..3dff0172143 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/TestIRAbs.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestIRAbs.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2022, Arm Limited. All rights reserved. + * Copyright (c) 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 @@ -24,18 +25,50 @@ package compiler.c2.irTests; import jdk.test.lib.Asserts; +import compiler.lib.generators.*; import compiler.lib.ir_framework.*; /* * @test - * @bug 8276673 8280089 + * @bug 8276673 8280089 8349563 * @summary Test abs nodes optimization in C2. - * @requires os.arch=="amd64" | os.arch=="x86_64" | os.arch=="aarch64" | os.arch=="riscv64" + * @key randomness * @library /test/lib / * @run driver compiler.c2.irTests.TestIRAbs */ public class TestIRAbs { + private static final RestrictableGenerator INTS = Generators.G.ints(); + private static final RestrictableGenerator LONGS = Generators.G.longs(); + + private static final IntRange INT_RANGE = IntRange.generate(INTS); + private static final IntRange INT_FULL_RANGE = new IntRange(Integer.MIN_VALUE, Integer.MAX_VALUE); + private static final IntRange INT_UNSIGNED_MAX = new IntRange(-1, Integer.MAX_VALUE); + private static final IntRange INT_POSITIVE = new IntRange(0, Integer.MAX_VALUE); + private static final IntRange INT_NEGATIVE = new IntRange(Integer.MIN_VALUE, 0); + private static final LongRange LONG_RANGE = LongRange.generate(LONGS); + private static final LongRange LONG_FULL_RANGE = new LongRange(Long.MIN_VALUE, Long.MAX_VALUE); + private static final LongRange LONG_UNSIGNED_MAX = new LongRange(-1, Long.MAX_VALUE); + private static final LongRange LONG_POSITIVE = new LongRange(0, Long.MAX_VALUE); + private static final LongRange LONG_NEGATIVE = new LongRange(Long.MIN_VALUE, 0); + + private static final int INT_1 = INTS.next(); + private static final int INT_2 = INTS.next(); + private static final int INT_3 = INTS.next(); + private static final int INT_4 = INTS.next(); + private static final int INT_5 = INTS.next(); + private static final int INT_6 = INTS.next(); + private static final int INT_7 = INTS.next(); + private static final int INT_8 = INTS.next(); + + private static final long LONG_1 = LONGS.next(); + private static final long LONG_2 = LONGS.next(); + private static final long LONG_3 = LONGS.next(); + private static final long LONG_4 = LONGS.next(); + private static final long LONG_5 = LONGS.next(); + private static final long LONG_6 = LONGS.next(); + private static final long LONG_7 = LONGS.next(); + private static final long LONG_8 = LONGS.next(); public static char [] cspecial = { 0, 42, 128, 256, 1024, 4096, 65535 @@ -103,7 +136,7 @@ public class TestIRAbs { } @Test - @IR(failOn = {IRNode.ABS_I, IRNode.ABS_L, IRNode.ABS_F, IRNode.ABS_D}) + @IR(failOn = {IRNode.ABS_I, IRNode.ABS_L, IRNode.ABS_F, IRNode.ABS_D}, applyIfPlatform = { "64-bit", "true" }) public void testAbsConstant() { // Test abs(constant) optimization for int Asserts.assertEquals(Integer.MAX_VALUE, Math.abs(Integer.MAX_VALUE)); @@ -160,14 +193,14 @@ public class TestIRAbs { } @Test - @IR(counts = {IRNode.ABS_L, "1"}) + @IR(counts = {IRNode.ABS_L, "1"}, applyIfPlatform = { "64-bit", "true" }) public long testLong0(long x) { return Math.abs(Math.abs(x)); // transformed to Math.abs(x) } @Test - @IR(failOn = {IRNode.SUB_L}) - @IR(counts = {IRNode.ABS_L, "1"}) + @IR(failOn = {IRNode.SUB_L}, applyIfPlatform = { "64-bit", "true" }) + @IR(counts = {IRNode.ABS_L, "1"}, applyIfPlatform = { "64-bit", "true" }) public long testLong1(long x) { return Math.abs(0 - x); // transformed to Math.abs(x) } @@ -229,4 +262,524 @@ public class TestIRAbs { Asserts.assertEquals(cspecial[i], (char) Math.abs(cspecial[i])); } } - } + + @Run(test = {"testIntRange1", "testIntRange2", "testIntRange3", "testIntRange4", + "testIntRangeFolding", "testIntFullRangeFolding", "testIntUnsignedMaxFolding", + "testIntPositiveRangeFolding", "testIntNegativeRangeFolding"}) + public void checkIntRanges(RunInfo info) { + for (int i : ispecial) { + checkIntRange(i); + } + + for (int j = 0; j < 20; j++) { + int i = INTS.next(); + checkIntRange(i); + } + } + + @DontCompile + public void checkIntRange(int i) { + Asserts.assertEquals(Math.abs((i & 7) - 4) > 4, testIntRange1(i)); + Asserts.assertEquals(Math.abs((i & 7) - 4) < 0, testIntRange2(i)); + Asserts.assertEquals(Math.abs(-((i & 7) + 2)) < 2, testIntRange3(i)); + Asserts.assertEquals(Math.abs(-((i & 7) + 2)) > 9, testIntRange4(i)); + Asserts.assertEquals(testIntRangeFoldingInterpreter(i), testIntRangeFolding(i)); + Asserts.assertEquals(testIntFullRangeFoldingInterpreter(i), testIntFullRangeFolding(i)); + Asserts.assertEquals(testIntUnsignedMaxFoldingInterpreter(i), testIntUnsignedMaxFolding(i)); + Asserts.assertEquals(testIntPositiveRangeFoldingInterpreter(i), testIntPositiveRangeFolding(i)); + Asserts.assertEquals(testIntNegativeRangeFoldingInterpreter(i), testIntNegativeRangeFolding(i)); + } + + @Run(test = {"testLongRange1", "testLongRange2", "testLongRange3", "testLongRange4", + "testLongRangeFolding", "testLongFullRangeFolding", "testLongUnsignedMaxFolding", + "testLongPositiveRangeFolding", "testLongNegativeRangeFolding"}) + public void checkLongRanges(RunInfo info) { + for (long l : lspecial) { + checkLongRange(l); + } + + for (int j = 0; j < 20; j++) { + long l = LONGS.next(); + checkLongRange(l); + } + } + + @DontCompile + public void checkLongRange(long l) { + Asserts.assertEquals(Math.abs((l & 7) - 4) > 4, testLongRange1(l)); + Asserts.assertEquals(Math.abs((l & 7) - 4) < 0, testLongRange2(l)); + Asserts.assertEquals(Math.abs(-((l & 7) + 2)) < 2, testLongRange3(l)); + Asserts.assertEquals(Math.abs(-((l & 7) + 2)) > 9, testLongRange4(l)); + Asserts.assertEquals(testLongRangeFoldingInterpreter(l), testLongRangeFolding(l)); + Asserts.assertEquals(testLongFullRangeFoldingInterpreter(l), testLongFullRangeFolding(l)); + Asserts.assertEquals(testLongUnsignedMaxFoldingInterpreter(l), testLongUnsignedMaxFolding(l)); + Asserts.assertEquals(testLongPositiveRangeFoldingInterpreter(l), testLongPositiveRangeFolding(l)); + Asserts.assertEquals(testLongNegativeRangeFoldingInterpreter(l), testLongNegativeRangeFolding(l)); + } + + // Int ranges + + @Test + @IR(failOn = { IRNode.ABS_I }) + public boolean testIntRange1(int in) { + // [-4, 3] => [0, 4] + return Math.abs((in & 7) - 4) > 4; + } + + @Test + @IR(failOn = { IRNode.ABS_I }) + public boolean testIntRange2(int in) { + // [-4, 3] => [0, 4] + return Math.abs((in & 7) - 4) < 0; + } + + @Test + @IR(failOn = { IRNode.ABS_I }) + public boolean testIntRange3(int in) { + // [-9, -2] => [2, 9] + return Math.abs(-((in & 7) + 2)) < 2; + } + + @Test + @IR(failOn = { IRNode.ABS_I }) + public boolean testIntRange4(int in) { + // [-9, -2] => [2, 9] + return Math.abs(-((in & 7) + 2)) > 9; + } + + @Test + public int testIntRangeFolding(int in) { + int c = INT_RANGE.clamp(in); + int v = Math.abs(c); + + int sum = 0; + if (v > INT_1) { sum += 1; } + if (v > INT_2) { sum += 2; } + if (v > INT_3) { sum += 4; } + if (v > INT_4) { sum += 8; } + if (v > INT_5) { sum += 16; } + if (v > INT_6) { sum += 32; } + if (v > INT_7) { sum += 64; } + if (v > INT_8) { sum += 128; } + + return sum; + } + + @DontCompile + public int testIntRangeFoldingInterpreter(int in) { + int c = INT_RANGE.clamp(in); + int v = Math.abs(c); + + int sum = 0; + if (v > INT_1) { sum += 1; } + if (v > INT_2) { sum += 2; } + if (v > INT_3) { sum += 4; } + if (v > INT_4) { sum += 8; } + if (v > INT_5) { sum += 16; } + if (v > INT_6) { sum += 32; } + if (v > INT_7) { sum += 64; } + if (v > INT_8) { sum += 128; } + + return sum; + } + + @Test + public int testIntFullRangeFolding(int in) { + int c = INT_FULL_RANGE.clamp(in); + int v = Math.abs(c); + + int sum = 0; + if (v > INT_1) { sum += 1; } + if (v > INT_2) { sum += 2; } + if (v > INT_3) { sum += 4; } + if (v > INT_4) { sum += 8; } + if (v > INT_5) { sum += 16; } + if (v > INT_6) { sum += 32; } + if (v > INT_7) { sum += 64; } + if (v > INT_8) { sum += 128; } + + return sum; + } + + @DontCompile + public int testIntFullRangeFoldingInterpreter(int in) { + int c = INT_FULL_RANGE.clamp(in); + int v = Math.abs(c); + + int sum = 0; + if (v > INT_1) { sum += 1; } + if (v > INT_2) { sum += 2; } + if (v > INT_3) { sum += 4; } + if (v > INT_4) { sum += 8; } + if (v > INT_5) { sum += 16; } + if (v > INT_6) { sum += 32; } + if (v > INT_7) { sum += 64; } + if (v > INT_8) { sum += 128; } + + return sum; + } + + @Test + public int testIntUnsignedMaxFolding(int in) { + int c = INT_UNSIGNED_MAX.clamp(in); + int v = Math.abs(c); + + int sum = 0; + if (v > INT_1) { sum += 1; } + if (v > INT_2) { sum += 2; } + if (v > INT_3) { sum += 4; } + if (v > INT_4) { sum += 8; } + if (v > INT_5) { sum += 16; } + if (v > INT_6) { sum += 32; } + if (v > INT_7) { sum += 64; } + if (v > INT_8) { sum += 128; } + + return sum; + } + + @DontCompile + public int testIntUnsignedMaxFoldingInterpreter(int in) { + int c = INT_UNSIGNED_MAX.clamp(in); + int v = Math.abs(c); + + int sum = 0; + if (v > INT_1) { sum += 1; } + if (v > INT_2) { sum += 2; } + if (v > INT_3) { sum += 4; } + if (v > INT_4) { sum += 8; } + if (v > INT_5) { sum += 16; } + if (v > INT_6) { sum += 32; } + if (v > INT_7) { sum += 64; } + if (v > INT_8) { sum += 128; } + + return sum; + } + + @Test + public int testIntPositiveRangeFolding(int in) { + int c = INT_POSITIVE.clamp(in); + int v = Math.abs(c); + + int sum = 0; + if (v > INT_1) { sum += 1; } + if (v > INT_2) { sum += 2; } + if (v > INT_3) { sum += 4; } + if (v > INT_4) { sum += 8; } + if (v > INT_5) { sum += 16; } + if (v > INT_6) { sum += 32; } + if (v > INT_7) { sum += 64; } + if (v > INT_8) { sum += 128; } + + return sum; + } + + @DontCompile + public int testIntPositiveRangeFoldingInterpreter(int in) { + int c = INT_POSITIVE.clamp(in); + int v = Math.abs(c); + + int sum = 0; + if (v > INT_1) { sum += 1; } + if (v > INT_2) { sum += 2; } + if (v > INT_3) { sum += 4; } + if (v > INT_4) { sum += 8; } + if (v > INT_5) { sum += 16; } + if (v > INT_6) { sum += 32; } + if (v > INT_7) { sum += 64; } + if (v > INT_8) { sum += 128; } + + return sum; + } + + @Test + public int testIntNegativeRangeFolding(int in) { + int c = INT_NEGATIVE.clamp(in); + int v = Math.abs(c); + + int sum = 0; + if (v > INT_1) { sum += 1; } + if (v > INT_2) { sum += 2; } + if (v > INT_3) { sum += 4; } + if (v > INT_4) { sum += 8; } + if (v > INT_5) { sum += 16; } + if (v > INT_6) { sum += 32; } + if (v > INT_7) { sum += 64; } + if (v > INT_8) { sum += 128; } + + return sum; + } + + @DontCompile + public int testIntNegativeRangeFoldingInterpreter(int in) { + int c = INT_NEGATIVE.clamp(in); + int v = Math.abs(c); + + int sum = 0; + if (v > INT_1) { sum += 1; } + if (v > INT_2) { sum += 2; } + if (v > INT_3) { sum += 4; } + if (v > INT_4) { sum += 8; } + if (v > INT_5) { sum += 16; } + if (v > INT_6) { sum += 32; } + if (v > INT_7) { sum += 64; } + if (v > INT_8) { sum += 128; } + + return sum; + } + + // Long ranges + + @Test + @IR(failOn = { IRNode.ABS_L }, applyIfPlatform = { "64-bit", "true" }) + public boolean testLongRange1(long in) { + // [-4, 3] => [0, 4] + return Math.abs((in & 7) - 4) > 4; + } + + @Test + @IR(failOn = { IRNode.ABS_L }, applyIfPlatform = { "64-bit", "true" }) + public boolean testLongRange2(long in) { + // [-4, 3] => [0, 4] + return Math.abs((in & 7) - 4) < 0; + } + + @Test + @IR(failOn = { IRNode.ABS_L }, applyIfPlatform = { "64-bit", "true" }) + public boolean testLongRange3(long in) { + // [-9, -2] => [2, 9] + return Math.abs(-((in & 7) + 2)) < 2; + } + + @Test + @IR(failOn = { IRNode.ABS_L }, applyIfPlatform = { "64-bit", "true" }) + public boolean testLongRange4(long in) { + // [-9, -2] => [2, 9] + return Math.abs(-((in & 7) + 2)) > 9; + } + + @Test + public int testLongRangeFolding(long in) { + long c = LONG_RANGE.clamp(in); + long v = Math.abs(c); + + int sum = 0; + if (v > LONG_1) { sum += 1; } + if (v > LONG_2) { sum += 2; } + if (v > LONG_3) { sum += 4; } + if (v > LONG_4) { sum += 8; } + if (v > LONG_5) { sum += 16; } + if (v > LONG_6) { sum += 32; } + if (v > LONG_7) { sum += 64; } + if (v > LONG_8) { sum += 128; } + + return sum; + } + + @DontCompile + public int testLongRangeFoldingInterpreter(long in) { + long c = LONG_RANGE.clamp(in); + long v = Math.abs(c); + + int sum = 0; + if (v > LONG_1) { sum += 1; } + if (v > LONG_2) { sum += 2; } + if (v > LONG_3) { sum += 4; } + if (v > LONG_4) { sum += 8; } + if (v > LONG_5) { sum += 16; } + if (v > LONG_6) { sum += 32; } + if (v > LONG_7) { sum += 64; } + if (v > LONG_8) { sum += 128; } + + return sum; + } + + @Test + public int testLongFullRangeFolding(long in) { + long c = LONG_FULL_RANGE.clamp(in); + long v = Math.abs(c); + + int sum = 0; + if (v > LONG_1) { sum += 1; } + if (v > LONG_2) { sum += 2; } + if (v > LONG_3) { sum += 4; } + if (v > LONG_4) { sum += 8; } + if (v > LONG_5) { sum += 16; } + if (v > LONG_6) { sum += 32; } + if (v > LONG_7) { sum += 64; } + if (v > LONG_8) { sum += 128; } + + return sum; + } + + @DontCompile + public int testLongFullRangeFoldingInterpreter(long in) { + long c = LONG_FULL_RANGE.clamp(in); + long v = Math.abs(c); + + int sum = 0; + if (v > LONG_1) { sum += 1; } + if (v > LONG_2) { sum += 2; } + if (v > LONG_3) { sum += 4; } + if (v > LONG_4) { sum += 8; } + if (v > LONG_5) { sum += 16; } + if (v > LONG_6) { sum += 32; } + if (v > LONG_7) { sum += 64; } + if (v > LONG_8) { sum += 128; } + + return sum; + } + + @Test + public int testLongUnsignedMaxFolding(long in) { + long c = LONG_UNSIGNED_MAX.clamp(in); + long v = Math.abs(c); + + int sum = 0; + if (v > LONG_1) { sum += 1; } + if (v > LONG_2) { sum += 2; } + if (v > LONG_3) { sum += 4; } + if (v > LONG_4) { sum += 8; } + if (v > LONG_5) { sum += 16; } + if (v > LONG_6) { sum += 32; } + if (v > LONG_7) { sum += 64; } + if (v > LONG_8) { sum += 128; } + + return sum; + } + + @DontCompile + public int testLongUnsignedMaxFoldingInterpreter(long in) { + long c = LONG_UNSIGNED_MAX.clamp(in); + long v = Math.abs(c); + + int sum = 0; + if (v > LONG_1) { sum += 1; } + if (v > LONG_2) { sum += 2; } + if (v > LONG_3) { sum += 4; } + if (v > LONG_4) { sum += 8; } + if (v > LONG_5) { sum += 16; } + if (v > LONG_6) { sum += 32; } + if (v > LONG_7) { sum += 64; } + if (v > LONG_8) { sum += 128; } + + return sum; + } + + @Test + public int testLongPositiveRangeFolding(long in) { + long c = LONG_POSITIVE.clamp(in); + long v = Math.abs(c); + + int sum = 0; + if (v > LONG_1) { sum += 1; } + if (v > LONG_2) { sum += 2; } + if (v > LONG_3) { sum += 4; } + if (v > LONG_4) { sum += 8; } + if (v > LONG_5) { sum += 16; } + if (v > LONG_6) { sum += 32; } + if (v > LONG_7) { sum += 64; } + if (v > LONG_8) { sum += 128; } + + return sum; + } + + @DontCompile + public int testLongPositiveRangeFoldingInterpreter(long in) { + long c = LONG_POSITIVE.clamp(in); + long v = Math.abs(c); + + int sum = 0; + if (v > LONG_1) { sum += 1; } + if (v > LONG_2) { sum += 2; } + if (v > LONG_3) { sum += 4; } + if (v > LONG_4) { sum += 8; } + if (v > LONG_5) { sum += 16; } + if (v > LONG_6) { sum += 32; } + if (v > LONG_7) { sum += 64; } + if (v > LONG_8) { sum += 128; } + + return sum; + } + + @Test + public int testLongNegativeRangeFolding(long in) { + long c = LONG_NEGATIVE.clamp(in); + long v = Math.abs(c); + + int sum = 0; + if (v > LONG_1) { sum += 1; } + if (v > LONG_2) { sum += 2; } + if (v > LONG_3) { sum += 4; } + if (v > LONG_4) { sum += 8; } + if (v > LONG_5) { sum += 16; } + if (v > LONG_6) { sum += 32; } + if (v > LONG_7) { sum += 64; } + if (v > LONG_8) { sum += 128; } + + return sum; + } + + @DontCompile + public int testLongNegativeRangeFoldingInterpreter(long in) { + long c = LONG_NEGATIVE.clamp(in); + long v = Math.abs(c); + + int sum = 0; + if (v > LONG_1) { sum += 1; } + if (v > LONG_2) { sum += 2; } + if (v > LONG_3) { sum += 4; } + if (v > LONG_4) { sum += 8; } + if (v > LONG_5) { sum += 16; } + if (v > LONG_6) { sum += 32; } + if (v > LONG_7) { sum += 64; } + if (v > LONG_8) { sum += 128; } + + return sum; + } + + record IntRange(int lo, int hi) { + IntRange { + if (lo > hi) { + throw new IllegalArgumentException("lo > hi"); + } + } + + int clamp(int v) { + return Math.min(hi, Math.max(v, lo)); + } + + static IntRange generate(Generator g) { + var a = g.next(); + var b = g.next(); + if (a > b) { + var tmp = a; + a = b; + b = tmp; + } + return new IntRange(a, b); + } + } + + record LongRange(long lo, long hi) { + LongRange { + if (lo > hi) { + throw new IllegalArgumentException("lo > hi"); + } + } + + long clamp(long v) { + return Math.min(hi, Math.max(v, lo)); + } + + static LongRange generate(Generator g) { + var a = g.next(); + var b = g.next(); + if (a > b) { + var tmp = a; + a = b; + b = tmp; + } + return new LongRange(a, b); + } + } +} From 4b3ec455c85314d051800a8f46dd8f5c93881e3a Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Wed, 10 Jun 2026 06:55:22 +0000 Subject: [PATCH 15/18] 8386098: Add empty MemRegion precondition to CardTable methods Reviewed-by: tschatzl, iwalulya, jsikstro --- src/hotspot/share/gc/shared/cardTable.cpp | 2 ++ src/hotspot/share/gc/shared/cardTableBarrierSet.inline.hpp | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/gc/shared/cardTable.cpp b/src/hotspot/share/gc/shared/cardTable.cpp index e6e3fdf3d82..dcf13ab48e9 100644 --- a/src/hotspot/share/gc/shared/cardTable.cpp +++ b/src/hotspot/share/gc/shared/cardTable.cpp @@ -194,6 +194,7 @@ void CardTable::resize_covered_region(MemRegion new_region) { // Note that these versions are precise! The scanning code has to handle the // fact that the write barrier may be either precise or imprecise. void CardTable::dirty_MemRegion(MemRegion mr) { + assert(!mr.is_empty(), "precondition"); assert(align_down(mr.start(), HeapWordSize) == mr.start(), "Unaligned start"); assert(align_up (mr.end(), HeapWordSize) == mr.end(), "Unaligned end" ); assert(_covered[0].contains(mr) || _covered[1].contains(mr), "precondition"); @@ -203,6 +204,7 @@ void CardTable::dirty_MemRegion(MemRegion mr) { } void CardTable::clear_MemRegion(MemRegion mr) { + assert(!mr.is_empty(), "precondition"); // Be conservative: only clean cards entirely contained within the // region. CardValue* cur; diff --git a/src/hotspot/share/gc/shared/cardTableBarrierSet.inline.hpp b/src/hotspot/share/gc/shared/cardTableBarrierSet.inline.hpp index f60a7f47a19..5c10a1618a5 100644 --- a/src/hotspot/share/gc/shared/cardTableBarrierSet.inline.hpp +++ b/src/hotspot/share/gc/shared/cardTableBarrierSet.inline.hpp @@ -130,7 +130,10 @@ oop_arraycopy_in_heap(arrayOop src_obj, size_t src_offset_in_bytes, T* src_raw, // pointer delta is scaled to number of elements (length field in // objArrayOop) which we assume is 32 bit. assert(pd == (size_t)(int)pd, "length field overflow"); - bs->write_ref_array((HeapWord*)dst_raw, pd); + if (pd > 0) { + // Copied at least one element; call the barrier. + bs->write_ref_array((HeapWord*)dst_raw, pd); + } return OopCopyResult::failed_check_class_cast; } } From 8630517d18c88775afe3f1f5d50d22b66f107f05 Mon Sep 17 00:00:00 2001 From: Ivan Walulya Date: Wed, 10 Jun 2026 08:18:12 +0000 Subject: [PATCH 16/18] 8386254: Parallel: Adjust Pointers should use stripes in young spaces Reviewed-by: ayang, tschatzl --- .../share/gc/parallel/psParallelCompact.cpp | 72 +++++++++---------- .../share/gc/parallel/psParallelCompact.hpp | 7 +- 2 files changed, 37 insertions(+), 42 deletions(-) diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.cpp b/src/hotspot/share/gc/parallel/psParallelCompact.cpp index a4a2bfe72c2..ff757f205a2 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp @@ -1268,8 +1268,7 @@ void PSParallelCompact::marking_phase(ParallelOldTracer *gc_tracer) { #endif } -template -void PSParallelCompact::adjust_in_space_helper(SpaceId id, Atomic* claim_counter, Func&& on_stripe) { +void PSParallelCompact::adjust_in_space_helper(SpaceId id, Atomic* claim_counter) { MutableSpace* sp = PSParallelCompact::space(id); HeapWord* const bottom = sp->bottom(); HeapWord* const top = sp->top(); @@ -1288,53 +1287,46 @@ void PSParallelCompact::adjust_in_space_helper(SpaceId id, Atomic* claim_c break; } HeapWord* stripe_end = MIN2(cur_stripe + stripe_size, top); - on_stripe(cur_stripe, stripe_end); + adjust_in_stripe(cur_stripe, stripe_end); + } +} + +size_t PSParallelCompact::adjust_in_obj_with_limit(HeapWord* obj_start, HeapWord* left, HeapWord* right) { + precond(mark_bitmap()->is_marked(obj_start)); + oop obj = cast_to_oop(obj_start); + return obj->oop_iterate_size(&pc_adjust_pointer_closure, MemRegion(left, right)); +} + +void PSParallelCompact::adjust_in_stripe(HeapWord* stripe_start, HeapWord* stripe_end) { + precond(_summary_data.is_region_aligned(stripe_start)); + + RegionData* cur_region = _summary_data.addr_to_region_ptr(stripe_start); + HeapWord* obj_start; + if (cur_region->partial_obj_size() != 0) { + obj_start = cur_region->partial_obj_addr(); + obj_start += adjust_in_obj_with_limit(obj_start, stripe_start, stripe_end); + } else { + obj_start = stripe_start; + } + + while (obj_start < stripe_end) { + obj_start = mark_bitmap()->find_obj_beg(obj_start, stripe_end); + if (obj_start >= stripe_end) { + break; + } + obj_start += adjust_in_obj_with_limit(obj_start, stripe_start, stripe_end); } } void PSParallelCompact::adjust_in_old_space(Atomic* claim_counter) { // Regions in old-space shouldn't be split. - assert(!_space_info[old_space_id].split_info().is_valid(), "inv"); + precond(!_space_info[old_space_id].split_info().is_valid()); - auto scan_obj_with_limit = [&] (HeapWord* obj_start, HeapWord* left, HeapWord* right) { - assert(mark_bitmap()->is_marked(obj_start), "inv"); - oop obj = cast_to_oop(obj_start); - return obj->oop_iterate_size(&pc_adjust_pointer_closure, MemRegion(left, right)); - }; - - adjust_in_space_helper(old_space_id, claim_counter, [&] (HeapWord* stripe_start, HeapWord* stripe_end) { - assert(_summary_data.is_region_aligned(stripe_start), "inv"); - RegionData* cur_region = _summary_data.addr_to_region_ptr(stripe_start); - HeapWord* obj_start; - if (cur_region->partial_obj_size() != 0) { - obj_start = cur_region->partial_obj_addr(); - obj_start += scan_obj_with_limit(obj_start, stripe_start, stripe_end); - } else { - obj_start = stripe_start; - } - - while (obj_start < stripe_end) { - obj_start = mark_bitmap()->find_obj_beg(obj_start, stripe_end); - if (obj_start >= stripe_end) { - break; - } - obj_start += scan_obj_with_limit(obj_start, stripe_start, stripe_end); - } - }); + adjust_in_space_helper(old_space_id, claim_counter); } void PSParallelCompact::adjust_in_young_space(SpaceId id, Atomic* claim_counter) { - adjust_in_space_helper(id, claim_counter, [](HeapWord* stripe_start, HeapWord* stripe_end) { - HeapWord* obj_start = stripe_start; - while (obj_start < stripe_end) { - obj_start = mark_bitmap()->find_obj_beg(obj_start, stripe_end); - if (obj_start >= stripe_end) { - break; - } - oop obj = cast_to_oop(obj_start); - obj_start += obj->oop_iterate_size(&pc_adjust_pointer_closure); - } - }); + adjust_in_space_helper(id, claim_counter); } void PSParallelCompact::adjust_pointers_in_spaces(uint worker_id, Atomic* claim_counters) { diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.hpp b/src/hotspot/share/gc/parallel/psParallelCompact.hpp index 25f4f66de6f..909005f5360 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.hpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.hpp @@ -760,8 +760,11 @@ public: // should_do_max_compaction controls whether all spaces for dead objs should be reclaimed. static bool invoke(bool clear_all_soft_refs, bool should_do_max_compaction); - template - static void adjust_in_space_helper(SpaceId id, Atomic* claim_counter, Func&& on_stripe); + static void adjust_in_space_helper(SpaceId id, Atomic* claim_counter); + + static size_t adjust_in_obj_with_limit(HeapWord* obj_start, HeapWord* left, HeapWord* right); + + static void adjust_in_stripe(HeapWord* stripe_start, HeapWord* stripe_end); static void adjust_in_old_space(Atomic* claim_counter); From 83495ebe78cff5d7f9422b40f023c16570fc1881 Mon Sep 17 00:00:00 2001 From: Gui Cao Date: Wed, 10 Jun 2026 08:43:57 +0000 Subject: [PATCH 17/18] 8386161: RISC-V: Auto-enable Zvkn/Zvkg extension features Reviewed-by: fyang, dzhang --- src/hotspot/cpu/riscv/globals_riscv.hpp | 6 +++--- src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp | 4 +--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/hotspot/cpu/riscv/globals_riscv.hpp b/src/hotspot/cpu/riscv/globals_riscv.hpp index 18ca120bdfa..f05b9ff7791 100644 --- a/src/hotspot/cpu/riscv/globals_riscv.hpp +++ b/src/hotspot/cpu/riscv/globals_riscv.hpp @@ -120,10 +120,10 @@ define_pd_global(intx, InlineSmallCode, 1000); product(bool, UseZvbb, false, EXPERIMENTAL, "Use Zvbb instructions") \ product(bool, UseZvbc, false, EXPERIMENTAL, "Use Zvbc instructions") \ product(bool, UseZvfh, false, DIAGNOSTIC, "Use Zvfh instructions") \ - product(bool, UseZvkn, false, EXPERIMENTAL, \ + product(bool, UseZvkg, false, DIAGNOSTIC, "Use Zvkg instructions") \ + product(bool, UseZvkn, false, DIAGNOSTIC, \ "Use Zvkn group extension, Zvkned, Zvknhb, Zvkb, Zvkt") \ product(bool, UseCtxFencei, false, EXPERIMENTAL, \ - "Use PR_RISCV_CTX_SW_FENCEI_ON to avoid explicit icache flush") \ - product(bool, UseZvkg, false, EXPERIMENTAL, "Use Zvkg instructions") + "Use PR_RISCV_CTX_SW_FENCEI_ON to avoid explicit icache flush") #endif // CPU_RISCV_GLOBALS_RISCV_HPP diff --git a/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp b/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp index 253f460dca3..a3bd1bfa870 100644 --- a/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp +++ b/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2023, Rivos Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -249,7 +249,6 @@ void RiscvHwprobe::add_features_from_query_result() { if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZVFH)) { VM_Version::ext_Zvfh.enable_feature(); } -#ifndef PRODUCT if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZVKNED) && is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZVKNHB) && is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZVKB) && @@ -259,7 +258,6 @@ void RiscvHwprobe::add_features_from_query_result() { if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZVKG)) { VM_Version::ext_Zvkg.enable_feature(); } -#endif // ====== non-extensions ====== // From e2bdec187e1662a5458ae8d93f0f336f1f1af28c Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Wed, 10 Jun 2026 10:13:43 +0000 Subject: [PATCH 18/18] 8386252: Shenandoah: Polish LRB argument preparation Reviewed-by: mdoerr, fyang --- .../shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp | 9 +++------ .../gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp | 9 +++------ .../shenandoah/shenandoahBarrierSetAssembler_riscv.cpp | 9 +++------ 3 files changed, 9 insertions(+), 18 deletions(-) diff --git a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp index 7731290c801..c590b6699c0 100644 --- a/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/gc/shenandoah/shenandoahBarrierSetAssembler_aarch64.cpp @@ -976,12 +976,9 @@ void ShenandoahBarrierStubC2::lrb(MacroAssembler& masm) { if (c_rarg0 == _obj) { __ lea(c_rarg1, _addr); } else if (c_rarg1 == _obj) { - // Set up arguments in reverse, and then flip them - __ lea(c_rarg0, _addr); - // flip them - __ mov(_tmp1, c_rarg0); - __ mov(c_rarg0, c_rarg1); - __ mov(c_rarg1, _tmp1); + __ mov(_tmp1, c_rarg1); + __ lea(c_rarg1, _addr); + __ mov(c_rarg0, _tmp1); } else { assert_different_registers(c_rarg1, _obj); __ lea(c_rarg1, _addr); diff --git a/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp b/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp index 823ff175379..582327282fd 100644 --- a/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp +++ b/src/hotspot/cpu/ppc/gc/shenandoah/shenandoahBarrierSetAssembler_ppc.cpp @@ -1210,12 +1210,9 @@ void ShenandoahBarrierStubC2::lrb(MacroAssembler& masm) { if (c_rarg0 == _obj) { __ addi(c_rarg1, _addr.base(), _addr.disp()); } else if (c_rarg1 == _obj) { - // Set up arguments in reverse, and then flip them - __ addi(c_rarg0, _addr.base(), _addr.disp()); - // flip them - __ mr(_tmp1, c_rarg0); - __ mr(c_rarg0, c_rarg1); - __ mr(c_rarg1, _tmp1); + __ mr(_tmp1, c_rarg1); + __ addi(c_rarg1, _addr.base(), _addr.disp()); + __ mr(c_rarg0, _tmp1); } else { assert_different_registers(c_rarg1, _obj); __ addi(c_rarg1, _addr.base(), _addr.disp()); diff --git a/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp index d30592d68f1..eec5f9a5165 100644 --- a/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/gc/shenandoah/shenandoahBarrierSetAssembler_riscv.cpp @@ -912,12 +912,9 @@ void ShenandoahBarrierStubC2::lrb(MacroAssembler& masm) { if (c_rarg0 == _obj) { __ la(c_rarg1, _addr); } else if (c_rarg1 == _obj) { - // Set up arguments in reverse, and then flip them - __ la(c_rarg0, _addr); - // flip them - __ mv(_tmp1, c_rarg0); - __ mv(c_rarg0, c_rarg1); - __ mv(c_rarg1, _tmp1); + __ mv(_tmp1, c_rarg1); + __ la(c_rarg1, _addr); + __ mv(c_rarg0, _tmp1); } else { assert_different_registers(c_rarg1, _obj); __ la(c_rarg1, _addr);