From b19e872192106f47c5d9b425230cc2bfe3e4786c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Tue, 30 Sep 2025 10:35:23 +0000 Subject: [PATCH 0001/1639] 8362573: Incorrect weight of the first ObjectAllocationSample JFR event (regression) Reviewed-by: egahlin --- .../checkpoint/jfrCheckpointManager.cpp | 30 +++++-- .../checkpoint/jfrCheckpointManager.hpp | 2 +- .../recorder/service/jfrRecorderService.cpp | 27 +----- .../share/jfr/support/jfrAllocationTracer.cpp | 5 +- .../jfr/support/jfrObjectAllocationSample.cpp | 57 +++++++------ .../jfr/support/jfrObjectAllocationSample.hpp | 4 +- ...ectAllocationSampleEventInitialWeight.java | 83 +++++++++++++++++++ 7 files changed, 147 insertions(+), 61 deletions(-) create mode 100644 test/jdk/jdk/jfr/event/allocation/TestObjectAllocationSampleEventInitialWeight.java diff --git a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp index b8ff3ba504a..ff688a297ed 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp @@ -676,18 +676,36 @@ void JfrCheckpointManager::write_simplified_vthread_checkpoint(traceid vtid) { JfrTypeManager::write_simplified_vthread_checkpoint(vtid); } -class JfrNotifyClosure : public ThreadClosure { +// Reset thread local state used for object allocation sampling. +static void clear_last_allocated_bytes(JavaThread* jt) { + assert(jt != nullptr, "invariant"); + assert(!JfrRecorder::is_recording(), "invariant"); + JfrThreadLocal* const tl = jt->jfr_thread_local(); + assert(tl != nullptr, "invariant"); + if (tl->last_allocated_bytes() != 0) { + tl->clear_last_allocated_bytes(); + } + assert(tl->last_allocated_bytes() == 0, "invariant"); +} + +class JfrNotifyClosure : public StackObj { + private: + bool _clear; public: - void do_thread(Thread* thread) { - assert(thread != nullptr, "invariant"); + JfrNotifyClosure(bool clear) : _clear(clear) {} + void do_thread(JavaThread* jt) { + assert(jt != nullptr, "invariant"); assert_locked_or_safepoint(Threads_lock); - JfrJavaEventWriter::notify(JavaThread::cast(thread)); + JfrJavaEventWriter::notify(jt); + if (_clear) { + clear_last_allocated_bytes(jt); + } } }; -void JfrCheckpointManager::notify_threads() { +void JfrCheckpointManager::notify_threads(bool clear /* false */) { assert(SafepointSynchronize::is_at_safepoint(), "invariant"); - JfrNotifyClosure tc; + JfrNotifyClosure tc(clear); JfrJavaThreadIterator iter; while (iter.has_next()) { tc.do_thread(iter.next()); diff --git a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.hpp b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.hpp index f9f8f1c26cf..f713a77e66d 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.hpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.hpp @@ -88,7 +88,7 @@ class JfrCheckpointManager : public JfrCHeapObj { size_t clear(); size_t write(); - void notify_threads(); + void notify_threads(bool clear = false); size_t write_static_type_set(Thread* thread); size_t write_threads(JavaThread* thread); diff --git a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp index 0087980f430..0e68e8a6032 100644 --- a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp +++ b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp @@ -122,30 +122,6 @@ const Thread* JfrRotationLock::_owner_thread = nullptr; const int JfrRotationLock::retry_wait_millis = 10; volatile int JfrRotationLock::_lock = 0; -// Reset thread local state used for object allocation sampling. -class ClearObjectAllocationSampling : public ThreadClosure { - public: - void do_thread(Thread* t) { - assert(t != nullptr, "invariant"); - t->jfr_thread_local()->clear_last_allocated_bytes(); - } -}; - -template -static inline void iterate(Iterator& it, ClearObjectAllocationSampling& coas) { - while (it.has_next()) { - coas.do_thread(it.next()); - } -} - -static void clear_object_allocation_sampling() { - ClearObjectAllocationSampling coas; - JfrJavaThreadIterator jit; - iterate(jit, coas); - JfrNonJavaThreadIterator njit; - iterate(njit, coas); -} - template class Content { private: @@ -472,7 +448,6 @@ void JfrRecorderService::clear() { } void JfrRecorderService::pre_safepoint_clear() { - clear_object_allocation_sampling(); _storage.clear(); JfrStackTraceRepository::clear(); } @@ -486,7 +461,7 @@ void JfrRecorderService::invoke_safepoint_clear() { void JfrRecorderService::safepoint_clear() { assert(SafepointSynchronize::is_at_safepoint(), "invariant"); _storage.clear(); - _checkpoint_manager.notify_threads(); + _checkpoint_manager.notify_threads(true); _chunkwriter.set_time_stamp(); JfrDeprecationManager::on_safepoint_clear(); JfrStackTraceRepository::clear(); diff --git a/src/hotspot/share/jfr/support/jfrAllocationTracer.cpp b/src/hotspot/share/jfr/support/jfrAllocationTracer.cpp index a1245d7bafe..5817ad194c2 100644 --- a/src/hotspot/share/jfr/support/jfrAllocationTracer.cpp +++ b/src/hotspot/share/jfr/support/jfrAllocationTracer.cpp @@ -22,6 +22,7 @@ * */ +#include "jfr/jfrEvents.hpp" #include "jfr/leakprofiler/leakProfiler.hpp" #include "jfr/support/jfrAllocationTracer.hpp" #include "jfr/support/jfrObjectAllocationSample.hpp" @@ -31,5 +32,7 @@ JfrAllocationTracer::JfrAllocationTracer(const Klass* klass, HeapWord* obj, size if (LeakProfiler::is_running()) { LeakProfiler::sample(obj, alloc_size, thread); } - JfrObjectAllocationSample::send_event(klass, alloc_size, outside_tlab, thread); + if (EventObjectAllocationSample::is_enabled()) { + JfrObjectAllocationSample::send_event(klass, alloc_size, outside_tlab, thread); + } } diff --git a/src/hotspot/share/jfr/support/jfrObjectAllocationSample.cpp b/src/hotspot/share/jfr/support/jfrObjectAllocationSample.cpp index 6a99271a80e..c337030bddd 100644 --- a/src/hotspot/share/jfr/support/jfrObjectAllocationSample.cpp +++ b/src/hotspot/share/jfr/support/jfrObjectAllocationSample.cpp @@ -26,7 +26,7 @@ #include "gc/shared/tlab_globals.hpp" #include "jfr/jfrEvents.hpp" #include "jfr/support/jfrObjectAllocationSample.hpp" -#include "jfr/support/jfrThreadLocal.hpp" +#include "runtime/javaThread.hpp" #include "utilities/globalDefinitions.hpp" inline bool send_allocation_sample(const Klass* klass, int64_t allocated_bytes, JfrThreadLocal* tl) { @@ -43,35 +43,42 @@ inline bool send_allocation_sample(const Klass* klass, int64_t allocated_bytes, return false; } -inline int64_t estimate_tlab_size_bytes(Thread* thread) { - const size_t desired_tlab_size_bytes = thread->tlab().desired_size() * HeapWordSize; - const size_t alignment_reserve_bytes = thread->tlab().alignment_reserve_in_bytes(); +inline int64_t estimate_tlab_size_bytes(JavaThread* jt) { + const size_t desired_tlab_size_bytes = jt->tlab().desired_size() * HeapWordSize; + const size_t alignment_reserve_bytes = jt->tlab().alignment_reserve_in_bytes(); assert(desired_tlab_size_bytes >= alignment_reserve_bytes, "invariant"); return static_cast(desired_tlab_size_bytes - alignment_reserve_bytes); } -inline int64_t load_allocated_bytes(JfrThreadLocal* tl, Thread* thread) { - const int64_t allocated_bytes = thread->allocated_bytes(); - return allocated_bytes == tl->last_allocated_bytes() ? 0 : allocated_bytes; +inline int64_t load_allocated_bytes(JfrThreadLocal* tl, JavaThread* jt) { + const int64_t allocated_bytes = jt->allocated_bytes(); + const int64_t last_allocated_bytes = tl->last_allocated_bytes(); + assert(allocated_bytes >= last_allocated_bytes, "invariant"); + if (last_allocated_bytes == 0) { + // Initialization. + tl->set_last_allocated_bytes(allocated_bytes); + return 0; + } + return allocated_bytes == last_allocated_bytes ? 0 : allocated_bytes; } // To avoid large objects from being undersampled compared to the regular TLAB samples, // the data amount is normalized as if it was a TLAB, giving a number of TLAB sampling attempts to the large object. -static void normalize_as_tlab_and_send_allocation_samples(const Klass* klass, int64_t obj_alloc_size_bytes, JfrThreadLocal* tl, Thread* thread) { - const int64_t allocated_bytes = load_allocated_bytes(tl, thread); +static void normalize_as_tlab_and_send_allocation_samples(const Klass* klass, + int64_t obj_alloc_size_bytes, + int64_t allocated_bytes, + JfrThreadLocal* tl, + JavaThread* jt) { assert(allocated_bytes > 0, "invariant"); // obj_alloc_size_bytes is already attributed to allocated_bytes at this point. if (!UseTLAB) { send_allocation_sample(klass, allocated_bytes, tl); return; } - const int64_t tlab_size_bytes = estimate_tlab_size_bytes(thread); - if (tlab_size_bytes <= 0) { + const int64_t tlab_size_bytes = estimate_tlab_size_bytes(jt); + if (tlab_size_bytes <= 0 || allocated_bytes - tl->last_allocated_bytes() < tlab_size_bytes) { // We don't get a TLAB, avoid endless loop below. return; } - if (allocated_bytes - tl->last_allocated_bytes() < tlab_size_bytes) { - return; - } assert(obj_alloc_size_bytes > 0, "invariant"); do { if (send_allocation_sample(klass, allocated_bytes, tl)) { @@ -81,17 +88,17 @@ static void normalize_as_tlab_and_send_allocation_samples(const Klass* klass, in } while (obj_alloc_size_bytes > 0); } -void JfrObjectAllocationSample::send_event(const Klass* klass, size_t alloc_size, bool outside_tlab, Thread* thread) { - assert(thread != nullptr, "invariant"); - JfrThreadLocal* const tl = thread->jfr_thread_local(); +void JfrObjectAllocationSample::send_event(const Klass* klass, size_t alloc_size, bool outside_tlab, JavaThread* jt) { + assert(klass != nullptr, "invariant"); + assert(jt != nullptr, "invariant"); + JfrThreadLocal* const tl = jt->jfr_thread_local(); assert(tl != nullptr, "invariant"); - if (outside_tlab) { - normalize_as_tlab_and_send_allocation_samples(klass, static_cast(alloc_size), tl, thread); - return; + const int64_t allocated_bytes = load_allocated_bytes(tl, jt); + if (allocated_bytes > 0) { + if (outside_tlab) { + normalize_as_tlab_and_send_allocation_samples(klass, static_cast(alloc_size), allocated_bytes, tl, jt); + return; + } + send_allocation_sample(klass, allocated_bytes, tl); } - const int64_t allocated_bytes = load_allocated_bytes(tl, thread); - if (allocated_bytes == 0) { - return; - } - send_allocation_sample(klass, allocated_bytes, tl); } diff --git a/src/hotspot/share/jfr/support/jfrObjectAllocationSample.hpp b/src/hotspot/share/jfr/support/jfrObjectAllocationSample.hpp index f58caf3c2a6..cb63d7e1e29 100644 --- a/src/hotspot/share/jfr/support/jfrObjectAllocationSample.hpp +++ b/src/hotspot/share/jfr/support/jfrObjectAllocationSample.hpp @@ -27,12 +27,12 @@ #include "memory/allStatic.hpp" +class JavaThread; class Klass; -class Thread; class JfrObjectAllocationSample : AllStatic { friend class JfrAllocationTracer; - static void send_event(const Klass* klass, size_t alloc_size, bool outside_tlab, Thread* thread); + static void send_event(const Klass* klass, size_t alloc_size, bool outside_tlab, JavaThread* jt); }; #endif // SHARE_JFR_SUPPORT_JFROBJECTALLOCATIONSAMPLE_HPP diff --git a/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationSampleEventInitialWeight.java b/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationSampleEventInitialWeight.java new file mode 100644 index 00000000000..598efd66a32 --- /dev/null +++ b/test/jdk/jdk/jfr/event/allocation/TestObjectAllocationSampleEventInitialWeight.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.jfr.event.allocation; + +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.CountDownLatch; +import java.util.List; +import jdk.jfr.Recording; +import jdk.jfr.consumer.RecordedEvent; +import jdk.jfr.consumer.RecordingStream; +import jdk.test.lib.jfr.EventNames; +import jdk.test.lib.jfr.Events; + +/** + * @test + * @summary Tests that the VM maintains proper initialization state for ObjectAllocationSampleEvent. + * @requires vm.hasJFR + * @library /test/lib + * @run main/othervm -XX:+UseTLAB -XX:TLABSize=2k -XX:-ResizeTLAB jdk.jfr.event.allocation.TestObjectAllocationSampleEventInitialWeight + */ +public class TestObjectAllocationSampleEventInitialWeight { + private static final String EVENT_NAME = EventNames.ObjectAllocationSample; + private static final int OBJECT_SIZE = 4 * 1024; + private static final int OBJECTS_TO_ALLOCATE = 16; + private static final int OBJECTS_TO_ALLOCATE_BEFORE_RECORDING = 1024; + private static final long BEFORE_RECORDING_SAMPLE_WEIGHT = OBJECT_SIZE * OBJECTS_TO_ALLOCATE_BEFORE_RECORDING; + + // Make sure allocation isn't dead code eliminated. + public static byte[] tmp; + + public static void main(String... args) throws Exception { + test(); + // Test again to ensure reset logic works correctly for subsequent physical recordings. + test(); + } + + private static void test() throws Exception { + long currentThreadId = Thread.currentThread().threadId(); + allocate(OBJECTS_TO_ALLOCATE_BEFORE_RECORDING); + try (Recording r = new Recording()) { + r.enable(EVENT_NAME); + r.start(); + allocate(OBJECTS_TO_ALLOCATE); + r.stop(); + List events = Events.fromRecording(r); + Events.hasEvents(events); + for (RecordedEvent event : events) { + if (currentThreadId == event.getThread().getJavaThreadId()) { + if (event.getLong("weight") >= BEFORE_RECORDING_SAMPLE_WEIGHT) { + throw new RuntimeException("Sample weight is not below " + BEFORE_RECORDING_SAMPLE_WEIGHT); + } + } + } + } + } + + private static void allocate(int number) throws Exception { + for (int i = 0; i < number; ++i) { + tmp = new byte[OBJECT_SIZE]; + } + } +} From ba0a6eed1a6a22bd4c1d159592b62e054afa401a Mon Sep 17 00:00:00 2001 From: Francesco Andreuzzi Date: Tue, 30 Sep 2025 10:41:13 +0000 Subject: [PATCH 0002/1639] 8368357: Some source files have initial blank lines Reviewed-by: stefank, ayang, serb, jwaters, jpai --- src/hotspot/share/cds/dumpTimeClassInfo.inline.hpp | 1 - src/hotspot/share/runtime/threads.cpp | 1 - src/hotspot/share/runtime/vmStructs.cpp | 1 - src/hotspot/share/services/threadIdTable.cpp | 1 - src/hotspot/share/services/threadIdTable.hpp | 1 - .../share/classes/sun/util/locale/UnicodeLocaleExtension.java | 1 - src/java.desktop/share/classes/java/awt/image/LookupOp.java | 1 - src/jdk.compiler/share/classes/com/sun/source/tree/UsesTree.java | 1 - 8 files changed, 8 deletions(-) diff --git a/src/hotspot/share/cds/dumpTimeClassInfo.inline.hpp b/src/hotspot/share/cds/dumpTimeClassInfo.inline.hpp index 658d3d31e50..2d0953288b0 100644 --- a/src/hotspot/share/cds/dumpTimeClassInfo.inline.hpp +++ b/src/hotspot/share/cds/dumpTimeClassInfo.inline.hpp @@ -1,4 +1,3 @@ - /* * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. diff --git a/src/hotspot/share/runtime/threads.cpp b/src/hotspot/share/runtime/threads.cpp index 0172fe4d69b..d098343c354 100644 --- a/src/hotspot/share/runtime/threads.cpp +++ b/src/hotspot/share/runtime/threads.cpp @@ -1,4 +1,3 @@ - /* * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021, Azul Systems, Inc. All rights reserved. diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index ac095be6936..10069e849bc 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -1,4 +1,3 @@ - /* * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. diff --git a/src/hotspot/share/services/threadIdTable.cpp b/src/hotspot/share/services/threadIdTable.cpp index 24ea28abaf6..1604927a0ac 100644 --- a/src/hotspot/share/services/threadIdTable.cpp +++ b/src/hotspot/share/services/threadIdTable.cpp @@ -1,4 +1,3 @@ - /* * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. diff --git a/src/hotspot/share/services/threadIdTable.hpp b/src/hotspot/share/services/threadIdTable.hpp index 12772aed88c..b295cec2514 100644 --- a/src/hotspot/share/services/threadIdTable.hpp +++ b/src/hotspot/share/services/threadIdTable.hpp @@ -1,4 +1,3 @@ - /* * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. diff --git a/src/java.base/share/classes/sun/util/locale/UnicodeLocaleExtension.java b/src/java.base/share/classes/sun/util/locale/UnicodeLocaleExtension.java index 634932e9e19..7f66febf65f 100644 --- a/src/java.base/share/classes/sun/util/locale/UnicodeLocaleExtension.java +++ b/src/java.base/share/classes/sun/util/locale/UnicodeLocaleExtension.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. diff --git a/src/java.desktop/share/classes/java/awt/image/LookupOp.java b/src/java.desktop/share/classes/java/awt/image/LookupOp.java index 5d11f78e76d..c8d8a703a3f 100644 --- a/src/java.desktop/share/classes/java/awt/image/LookupOp.java +++ b/src/java.desktop/share/classes/java/awt/image/LookupOp.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. diff --git a/src/jdk.compiler/share/classes/com/sun/source/tree/UsesTree.java b/src/jdk.compiler/share/classes/com/sun/source/tree/UsesTree.java index 9b52eb29e1b..d14257de626 100644 --- a/src/jdk.compiler/share/classes/com/sun/source/tree/UsesTree.java +++ b/src/jdk.compiler/share/classes/com/sun/source/tree/UsesTree.java @@ -1,4 +1,3 @@ - /* * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. From 64c46d8efc27911b8667c3974275c075cf79a311 Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Tue, 30 Sep 2025 11:32:44 +0000 Subject: [PATCH 0003/1639] 8367953: JFR sampler threads does not appear in thread dump Reviewed-by: mgronlun --- .../jfr/periodic/sampling/jfrCPUTimeThreadSampler.cpp | 7 +++++++ .../share/jfr/periodic/sampling/jfrThreadSampler.cpp | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.cpp b/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.cpp index 3fca3ad7631..2ce1a93455b 100644 --- a/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.cpp +++ b/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.cpp @@ -275,6 +275,7 @@ public: void handle_timer_signal(siginfo_t* info, void* context); bool init_timers(); void stop_timer(); + virtual void print_on(outputStream* st) const; void trigger_async_processing_of_cpu_time_jfr_requests(); @@ -788,6 +789,12 @@ void JfrCPUSamplerThread::stop_timer() { VMThread::execute(&op); } +void JfrCPUSamplerThread::print_on(outputStream* st) const { + st->print("\"%s\" ", name()); + Thread::print_on(st); + st->cr(); +} + void JfrCPUSamplerThread::recompute_period_if_needed() { int64_t current_period = get_sampling_period(); int64_t period = _throttle.compute_sampling_period(); diff --git a/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp b/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp index ae79c8bb6e3..7e7747ba396 100644 --- a/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp +++ b/src/hotspot/share/jfr/periodic/sampling/jfrThreadSampler.cpp @@ -85,6 +85,7 @@ class JfrSamplerThread : public NonJavaThread { bool is_JfrSampler_thread() const { return true; } int64_t java_period() const { return AtomicAccess::load(&_java_period_millis); }; int64_t native_period() const { return AtomicAccess::load(&_native_period_millis); }; + virtual void print_on(outputStream* st) const; }; JfrSamplerThread::JfrSamplerThread(int64_t java_period_millis, int64_t native_period_millis, u4 max_frames) : @@ -384,6 +385,12 @@ void JfrSamplerThread::set_native_period(int64_t period_millis) { AtomicAccess::store(&_native_period_millis, period_millis); } +void JfrSamplerThread::print_on(outputStream* st) const { + st->print("\"%s\" ", name()); + Thread::print_on(st); + st->cr(); +} + // JfrThreadSampler; static JfrThreadSampler* _instance = nullptr; From 8606d3f8405b73878a1319ba3574ef69349aa2a1 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Tue, 30 Sep 2025 11:54:37 +0000 Subject: [PATCH 0004/1639] 8365060: Historical data for JDK 8 should include the jdk.net package Reviewed-by: shade, liach --- .../share/data/symbols/include.list | 1 + .../share/data/symbols/java.base-8.sym.txt | 6 +- .../share/data/symbols/java.base-9.sym.txt | 22 +++--- .../share/data/symbols/java.desktop-8.sym.txt | 6 +- .../share/data/symbols/java.desktop-9.sym.txt | 53 +++++++------ .../data/symbols/java.xml.bind-9.sym.txt | 4 +- .../data/symbols/jdk.management-8.sym.txt | 6 +- .../data/symbols/jdk.management-9.sym.txt | 6 +- .../share/data/symbols/jdk.net-8.sym.txt | 76 +++++++++++++++++++ .../share/data/symbols/jdk.net-9.sym.txt | 33 +------- src/jdk.compiler/share/data/symbols/symbols | 2 +- .../tools/javac/platform/CompilationTest.java | 75 ++++++++++++++++++ .../tools/javac/sym/ElementStructureTest.java | 12 +-- 13 files changed, 219 insertions(+), 83 deletions(-) create mode 100644 src/jdk.compiler/share/data/symbols/jdk.net-8.sym.txt create mode 100644 test/langtools/tools/javac/platform/CompilationTest.java diff --git a/src/jdk.compiler/share/data/symbols/include.list b/src/jdk.compiler/share/data/symbols/include.list index b99422a60e3..b2502f18fa4 100644 --- a/src/jdk.compiler/share/data/symbols/include.list +++ b/src/jdk.compiler/share/data/symbols/include.list @@ -267,6 +267,7 @@ +com/sun/management/ +com/sun/nio/sctp/ +jdk/ ++jdk/net/ # #Exported(true) in 8u40: # diff --git a/src/jdk.compiler/share/data/symbols/java.base-8.sym.txt b/src/jdk.compiler/share/data/symbols/java.base-8.sym.txt index 051003c2799..3f0b74098ef 100644 --- a/src/jdk.compiler/share/data/symbols/java.base-8.sym.txt +++ b/src/jdk.compiler/share/data/symbols/java.base-8.sym.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -1711,6 +1711,7 @@ field name SHARADA descriptor Ljava/lang/Character$UnicodeBlock; flags 19 field name TAKRI descriptor Ljava/lang/Character$UnicodeBlock; flags 19 field name MIAO descriptor Ljava/lang/Character$UnicodeBlock; flags 19 field name ARABIC_MATHEMATICAL_ALPHABETIC_SYMBOLS descriptor Ljava/lang/Character$UnicodeBlock; flags 19 +field name CJK_UNIFIED_IDEOGRAPHS_EXTENSION_E descriptor Ljava/lang/Character$UnicodeBlock; flags 19 method name of descriptor (C)Ljava/lang/Character$UnicodeBlock; flags 9 method name of descriptor (I)Ljava/lang/Character$UnicodeBlock; flags 9 method name forName descriptor (Ljava/lang/String;)Ljava/lang/Character$UnicodeBlock; flags 19 @@ -2078,7 +2079,7 @@ field name POSITIVE_INFINITY descriptor F constantValue Infinity flags 19 field name NEGATIVE_INFINITY descriptor F constantValue -Infinity flags 19 field name NaN descriptor F constantValue NaN flags 19 field name MAX_VALUE descriptor F constantValue 3.4028235E38 flags 19 -field name MIN_NORMAL descriptor F constantValue 1.17549435E-38 flags 19 +field name MIN_NORMAL descriptor F constantValue 1.1754944E-38 flags 19 field name MIN_VALUE descriptor F constantValue 1.4E-45 flags 19 field name MAX_EXPONENT descriptor I constantValue 127 flags 19 field name MIN_EXPONENT descriptor I constantValue -126 flags 19 @@ -3574,6 +3575,7 @@ method name get descriptor ()Ljava/lang/Object; flags 1 signature ()TT; method name clear descriptor ()V flags 1 method name isEnqueued descriptor ()Z flags 1 method name enqueue descriptor ()Z flags 1 +method name clone descriptor ()Ljava/lang/Object; thrownTypes java/lang/CloneNotSupportedException flags 4 class name java/lang/ref/ReferenceQueue header extends java/lang/Object flags 21 signature Ljava/lang/Object; classAnnotations @Ljdk/Profile+Annotation;(value=I1) diff --git a/src/jdk.compiler/share/data/symbols/java.base-9.sym.txt b/src/jdk.compiler/share/data/symbols/java.base-9.sym.txt index 99a4f8e9f0e..7ea597bda46 100644 --- a/src/jdk.compiler/share/data/symbols/java.base-9.sym.txt +++ b/src/jdk.compiler/share/data/symbols/java.base-9.sym.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -165,10 +165,6 @@ header extends java/lang/Object implements java/io/Serializable,java/lang/Compar innerclass innerClass java/lang/Character$UnicodeScript outerClass java/lang/Character innerClassName UnicodeScript flags 4019 innerclass innerClass java/lang/Character$UnicodeBlock outerClass java/lang/Character innerClassName UnicodeBlock flags 19 innerclass innerClass java/lang/Character$Subset outerClass java/lang/Character innerClassName Subset flags 9 -field name DIRECTIONALITY_LEFT_TO_RIGHT_ISOLATE descriptor B constantValue 19 flags 19 -field name DIRECTIONALITY_RIGHT_TO_LEFT_ISOLATE descriptor B constantValue 20 flags 19 -field name DIRECTIONALITY_FIRST_STRONG_ISOLATE descriptor B constantValue 21 flags 19 -field name DIRECTIONALITY_POP_DIRECTIONAL_ISOLATE descriptor B constantValue 22 flags 19 -method name descriptor (C)V -method name valueOf descriptor (C)Ljava/lang/Character; -method name charValue descriptor ()C @@ -176,6 +172,10 @@ field name DIRECTIONALITY_POP_DIRECTIONAL_ISOLATE descriptor B constantValue 22 -method name isJavaLetterOrDigit descriptor (C)Z -method name isSpace descriptor (C)Z -method name reverseBytes descriptor (C)C +field name DIRECTIONALITY_LEFT_TO_RIGHT_ISOLATE descriptor B constantValue 19 flags 19 +field name DIRECTIONALITY_RIGHT_TO_LEFT_ISOLATE descriptor B constantValue 20 flags 19 +field name DIRECTIONALITY_FIRST_STRONG_ISOLATE descriptor B constantValue 21 flags 19 +field name DIRECTIONALITY_POP_DIRECTIONAL_ISOLATE descriptor B constantValue 22 flags 19 method name descriptor (C)V flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") method name valueOf descriptor (C)Ljava/lang/Character; flags 9 runtimeAnnotations @Ljdk/internal/HotSpotIntrinsicCandidate; method name charValue descriptor ()C flags 1 runtimeAnnotations @Ljdk/internal/HotSpotIntrinsicCandidate; @@ -229,7 +229,6 @@ field name EARLY_DYNASTIC_CUNEIFORM descriptor Ljava/lang/Character$UnicodeBlock field name ANATOLIAN_HIEROGLYPHS descriptor Ljava/lang/Character$UnicodeBlock; flags 19 field name SUTTON_SIGNWRITING descriptor Ljava/lang/Character$UnicodeBlock; flags 19 field name SUPPLEMENTAL_SYMBOLS_AND_PICTOGRAPHS descriptor Ljava/lang/Character$UnicodeBlock; flags 19 -field name CJK_UNIFIED_IDEOGRAPHS_EXTENSION_E descriptor Ljava/lang/Character$UnicodeBlock; flags 19 class name java/lang/Character$UnicodeScript field name CAUCASIAN_ALBANIAN descriptor Ljava/lang/Character$UnicodeScript; flags 4019 @@ -711,7 +710,6 @@ innerclass innerClass java/lang/module/ModuleDescriptor$Opens outerClass java/la innerclass innerClass java/lang/module/ModuleDescriptor$Exports outerClass java/lang/module/ModuleDescriptor innerClassName Exports flags 19 innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 -field name inCheck descriptor Z -field name inCheck descriptor Z flags 4 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="1.2") -method name getInCheck descriptor ()Z -method name getClassContext descriptor ()[Ljava/lang/Class; -method name currentClassLoader descriptor ()Ljava/lang/ClassLoader; @@ -725,6 +723,7 @@ field name inCheck descriptor Z flags 4 deprecated true runtimeAnnotations @Ljav -method name checkSystemClipboardAccess descriptor ()V -method name checkAwtEventQueueAccess descriptor ()V -method name checkMemberAccess descriptor (Ljava/lang/Class;I)V +field name inCheck descriptor Z flags 4 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="1.2") method name getInCheck descriptor ()Z flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="1.2") method name getClassContext descriptor ()[Ljava/lang/Class; flags 104 signature ()[Ljava/lang/Class<*>; method name currentClassLoader descriptor ()Ljava/lang/ClassLoader; flags 4 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="1.2") @@ -1404,6 +1403,7 @@ method name clean descriptor ()V flags 401 class name java/lang/ref/Reference -method name get descriptor ()Ljava/lang/Object; +-method name clone descriptor ()Ljava/lang/Object; method name get descriptor ()Ljava/lang/Object; flags 1 signature ()TT; runtimeAnnotations @Ljdk/internal/HotSpotIntrinsicCandidate; method name reachabilityFence descriptor (Ljava/lang/Object;)V flags 9 runtimeAnnotations @Ljdk/internal/vm/annotation/DontInline; @@ -1515,6 +1515,9 @@ class name java/math/BigDecimal -field name ROUND_HALF_DOWN descriptor I -field name ROUND_HALF_EVEN descriptor I -field name ROUND_UNNECESSARY descriptor I +-method name divide descriptor (Ljava/math/BigDecimal;II)Ljava/math/BigDecimal; +-method name divide descriptor (Ljava/math/BigDecimal;I)Ljava/math/BigDecimal; +-method name setScale descriptor (II)Ljava/math/BigDecimal; field name ROUND_UP descriptor I constantValue 0 flags 19 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") field name ROUND_DOWN descriptor I constantValue 1 flags 19 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") field name ROUND_CEILING descriptor I constantValue 2 flags 19 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") @@ -1523,9 +1526,6 @@ field name ROUND_HALF_UP descriptor I constantValue 4 flags 19 deprecated true r field name ROUND_HALF_DOWN descriptor I constantValue 5 flags 19 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") field name ROUND_HALF_EVEN descriptor I constantValue 6 flags 19 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") field name ROUND_UNNECESSARY descriptor I constantValue 7 flags 19 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") --method name divide descriptor (Ljava/math/BigDecimal;II)Ljava/math/BigDecimal; --method name divide descriptor (Ljava/math/BigDecimal;I)Ljava/math/BigDecimal; --method name setScale descriptor (II)Ljava/math/BigDecimal; method name divide descriptor (Ljava/math/BigDecimal;II)Ljava/math/BigDecimal; flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") method name divide descriptor (Ljava/math/BigDecimal;I)Ljava/math/BigDecimal; flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") method name sqrt descriptor (Ljava/math/MathContext;)Ljava/math/BigDecimal; flags 1 @@ -2189,8 +2189,8 @@ innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang class name java/time/LocalDate header extends java/lang/Object implements java/time/temporal/Temporal,java/time/temporal/TemporalAdjuster,java/time/chrono/ChronoLocalDate,java/io/Serializable flags 31 innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 -field name EPOCH descriptor Ljava/time/LocalDate; flags 19 -method name getEra descriptor ()Ljava/time/chrono/Era; +field name EPOCH descriptor Ljava/time/LocalDate; flags 19 method name ofInstant descriptor (Ljava/time/Instant;Ljava/time/ZoneId;)Ljava/time/LocalDate; flags 9 method name getEra descriptor ()Ljava/time/chrono/IsoEra; flags 1 method name datesUntil descriptor (Ljava/time/LocalDate;)Ljava/util/stream/Stream; flags 1 signature (Ljava/time/LocalDate;)Ljava/util/stream/Stream; diff --git a/src/jdk.compiler/share/data/symbols/java.desktop-8.sym.txt b/src/jdk.compiler/share/data/symbols/java.desktop-8.sym.txt index 3daa15e5081..782c96da30c 100644 --- a/src/jdk.compiler/share/data/symbols/java.desktop-8.sym.txt +++ b/src/jdk.compiler/share/data/symbols/java.desktop-8.sym.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -666,7 +666,6 @@ innerclass innerClass java/awt/Component$BaselineResizeBehavior outerClass java/ innerclass innerClass java/awt/Component$FlipBufferStrategy outerClass java/awt/Component innerClassName FlipBufferStrategy flags 4 innerclass innerClass java/awt/Component$BltBufferStrategy outerClass java/awt/Component innerClassName BltBufferStrategy flags 4 innerclass innerClass java/awt/Component$AccessibleAWTComponent outerClass java/awt/Component innerClassName AccessibleAWTComponent flags 404 -innerclass innerClass sun/awt/CausedFocusEvent$Cause outerClass sun/awt/CausedFocusEvent innerClassName Cause flags 4019 field name TOP_ALIGNMENT descriptor F constantValue 0.0 flags 19 field name CENTER_ALIGNMENT descriptor F constantValue 0.5 flags 19 field name BOTTOM_ALIGNMENT descriptor F constantValue 1.0 flags 19 @@ -2116,7 +2115,6 @@ method name postProcessKeyEvent descriptor (Ljava/awt/event/KeyEvent;)Z flags 40 class name java/awt/KeyboardFocusManager header extends java/lang/Object implements java/awt/KeyEventDispatcher,java/awt/KeyEventPostProcessor flags 421 classAnnotations @Ljdk/Profile+Annotation;(value=I4) -innerclass innerClass sun/awt/CausedFocusEvent$Cause outerClass sun/awt/CausedFocusEvent innerClassName Cause flags 4019 field name FORWARD_TRAVERSAL_KEYS descriptor I constantValue 0 flags 19 field name BACKWARD_TRAVERSAL_KEYS descriptor I constantValue 1 flags 19 field name UP_CYCLE_TRAVERSAL_KEYS descriptor I constantValue 2 flags 19 @@ -7473,7 +7471,6 @@ method name select descriptor (I)V flags 401 class name java/awt/peer/ComponentPeer header extends java/lang/Object flags 601 classAnnotations @Ljdk/Profile+Annotation;(value=I4)@Lsun/Proprietary+Annotation; -innerclass innerClass sun/awt/CausedFocusEvent$Cause outerClass sun/awt/CausedFocusEvent innerClassName Cause flags 4019 innerclass innerClass java/awt/BufferCapabilities$FlipContents outerClass java/awt/BufferCapabilities innerClassName FlipContents flags 19 field name SET_LOCATION descriptor I constantValue 1 flags 19 field name SET_SIZE descriptor I constantValue 2 flags 19 @@ -15617,6 +15614,7 @@ method name descriptor (Ljavax/swing/JSpinner;)V flags 1 method name descriptor (Ljavax/swing/JSpinner;Ljava/lang/String;)V flags 1 method name getFormat descriptor ()Ljava/text/DecimalFormat; flags 1 method name getModel descriptor ()Ljavax/swing/SpinnerNumberModel; flags 1 +method name setComponentOrientation descriptor (Ljava/awt/ComponentOrientation;)V flags 1 class name javax/swing/JSplitPane header extends javax/swing/JComponent implements javax/accessibility/Accessible flags 21 classAnnotations @Ljdk/Profile+Annotation;(value=I4) diff --git a/src/jdk.compiler/share/data/symbols/java.desktop-9.sym.txt b/src/jdk.compiler/share/data/symbols/java.desktop-9.sym.txt index cf0ab3466a8..039610548bb 100644 --- a/src/jdk.compiler/share/data/symbols/java.desktop-9.sym.txt +++ b/src/jdk.compiler/share/data/symbols/java.desktop-9.sym.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -789,6 +789,7 @@ innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang -field name BUTTON1_MASK descriptor I -field name BUTTON2_MASK descriptor I -field name BUTTON3_MASK descriptor I +-method name getModifiers descriptor ()I field name SHIFT_MASK descriptor I constantValue 1 flags 19 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") field name CTRL_MASK descriptor I constantValue 2 flags 19 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") field name META_MASK descriptor I constantValue 4 flags 19 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") @@ -797,7 +798,6 @@ field name ALT_GRAPH_MASK descriptor I constantValue 32 flags 19 deprecated true field name BUTTON1_MASK descriptor I constantValue 16 flags 19 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") field name BUTTON2_MASK descriptor I constantValue 8 flags 19 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") field name BUTTON3_MASK descriptor I constantValue 4 flags 19 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") --method name getModifiers descriptor ()I method name getModifiers descriptor ()I flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") class name java/awt/event/InputMethodEvent @@ -1354,10 +1354,10 @@ innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang class name java/beans/beancontext/BeanContextServiceAvailableEvent -field name serviceClass descriptor Ljava/lang/Class; -field name serviceClass descriptor Ljava/lang/Class; flags 4 signature Ljava/lang/Class<*>; -method name descriptor (Ljava/beans/beancontext/BeanContextServices;Ljava/lang/Class;)V -method name getServiceClass descriptor ()Ljava/lang/Class; -method name getCurrentServiceSelectors descriptor ()Ljava/util/Iterator; +field name serviceClass descriptor Ljava/lang/Class; flags 4 signature Ljava/lang/Class<*>; method name descriptor (Ljava/beans/beancontext/BeanContextServices;Ljava/lang/Class;)V flags 1 signature (Ljava/beans/beancontext/BeanContextServices;Ljava/lang/Class<*>;)V method name getServiceClass descriptor ()Ljava/lang/Class; flags 1 signature ()Ljava/lang/Class<*>; method name getCurrentServiceSelectors descriptor ()Ljava/util/Iterator; flags 1 signature ()Ljava/util/Iterator<*>; @@ -1370,10 +1370,10 @@ method name getCurrentServiceSelectors descriptor (Ljava/beans/beancontext/BeanC class name java/beans/beancontext/BeanContextServiceRevokedEvent -field name serviceClass descriptor Ljava/lang/Class; -field name serviceClass descriptor Ljava/lang/Class; flags 4 signature Ljava/lang/Class<*>; -method name descriptor (Ljava/beans/beancontext/BeanContextServices;Ljava/lang/Class;Z)V -method name getServiceClass descriptor ()Ljava/lang/Class; -method name isServiceClass descriptor (Ljava/lang/Class;)Z +field name serviceClass descriptor Ljava/lang/Class; flags 4 signature Ljava/lang/Class<*>; method name descriptor (Ljava/beans/beancontext/BeanContextServices;Ljava/lang/Class;Z)V flags 1 signature (Ljava/beans/beancontext/BeanContextServices;Ljava/lang/Class<*>;Z)V method name getServiceClass descriptor ()Ljava/lang/Class; flags 1 signature ()Ljava/lang/Class<*>; method name isServiceClass descriptor (Ljava/lang/Class;)Z flags 1 signature (Ljava/lang/Class<*>;)Z @@ -1402,8 +1402,6 @@ innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassNam innerclass innerClass java/beans/beancontext/BeanContextSupport$BCSIterator outerClass java/beans/beancontext/BeanContextSupport innerClassName BCSIterator flags 1c -field name services descriptor Ljava/util/HashMap; -field name bcsListeners descriptor Ljava/util/ArrayList; -field name services descriptor Ljava/util/HashMap; flags 84 signature Ljava/util/HashMap; -field name bcsListeners descriptor Ljava/util/ArrayList; flags 84 signature Ljava/util/ArrayList; -method name createBCSSServiceProvider descriptor (Ljava/lang/Class;Ljava/beans/beancontext/BeanContextServiceProvider;)Ljava/beans/beancontext/BeanContextServicesSupport$BCSSServiceProvider; -method name addService descriptor (Ljava/lang/Class;Ljava/beans/beancontext/BeanContextServiceProvider;)Z -method name addService descriptor (Ljava/lang/Class;Ljava/beans/beancontext/BeanContextServiceProvider;Z)Z @@ -1414,6 +1412,8 @@ field name bcsListeners descriptor Ljava/util/ArrayList; flags 84 signature Ljav -method name getCurrentServiceSelectors descriptor (Ljava/lang/Class;)Ljava/util/Iterator; -method name fireServiceAdded descriptor (Ljava/lang/Class;)V -method name fireServiceRevoked descriptor (Ljava/lang/Class;Z)V +field name services descriptor Ljava/util/HashMap; flags 84 signature Ljava/util/HashMap; +field name bcsListeners descriptor Ljava/util/ArrayList; flags 84 signature Ljava/util/ArrayList; method name createBCSSServiceProvider descriptor (Ljava/lang/Class;Ljava/beans/beancontext/BeanContextServiceProvider;)Ljava/beans/beancontext/BeanContextServicesSupport$BCSSServiceProvider; flags 4 signature (Ljava/lang/Class<*>;Ljava/beans/beancontext/BeanContextServiceProvider;)Ljava/beans/beancontext/BeanContextServicesSupport$BCSSServiceProvider; method name addService descriptor (Ljava/lang/Class;Ljava/beans/beancontext/BeanContextServiceProvider;)Z flags 1 signature (Ljava/lang/Class<*>;Ljava/beans/beancontext/BeanContextServiceProvider;)Z method name addService descriptor (Ljava/lang/Class;Ljava/beans/beancontext/BeanContextServiceProvider;Z)Z flags 4 signature (Ljava/lang/Class<*>;Ljava/beans/beancontext/BeanContextServiceProvider;Z)Z @@ -1448,12 +1448,12 @@ innerclass innerClass java/beans/beancontext/BeanContextSupport$BCSIterator oute innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 -field name children descriptor Ljava/util/HashMap; -field name bcmListeners descriptor Ljava/util/ArrayList; -field name children descriptor Ljava/util/HashMap; flags 84 signature Ljava/util/HashMap; -field name bcmListeners descriptor Ljava/util/ArrayList; flags 84 signature Ljava/util/ArrayList; -method name iterator descriptor ()Ljava/util/Iterator; -method name bcsChildren descriptor ()Ljava/util/Iterator; -method name serialize descriptor (Ljava/io/ObjectOutputStream;Ljava/util/Collection;)V -method name classEquals descriptor (Ljava/lang/Class;Ljava/lang/Class;)Z +field name children descriptor Ljava/util/HashMap; flags 84 signature Ljava/util/HashMap; +field name bcmListeners descriptor Ljava/util/ArrayList; flags 84 signature Ljava/util/ArrayList; method name iterator descriptor ()Ljava/util/Iterator; flags 1 signature ()Ljava/util/Iterator; method name bcsChildren descriptor ()Ljava/util/Iterator; flags 4 signature ()Ljava/util/Iterator; method name serialize descriptor (Ljava/io/ObjectOutputStream;Ljava/util/Collection;)V thrownTypes java/io/IOException flags 14 signature (Ljava/io/ObjectOutputStream;Ljava/util/Collection<*>;)V @@ -2028,10 +2028,10 @@ method name getTagNames descriptor ()Ljava/util/SortedSet; flags 1 signature ()L class name javax/imageio/spi/ImageReaderSpi -field name STANDARD_INPUT_TYPE descriptor [Ljava/lang/Class; -field name inputTypes descriptor [Ljava/lang/Class; -field name STANDARD_INPUT_TYPE descriptor [Ljava/lang/Class; flags 19 deprecated true signature [Ljava/lang/Class<*>; runtimeAnnotations @Ljava/lang/Deprecated; -field name inputTypes descriptor [Ljava/lang/Class; flags 4 signature [Ljava/lang/Class<*>; -method name descriptor (Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Class;[Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)V -method name getInputTypes descriptor ()[Ljava/lang/Class; +field name STANDARD_INPUT_TYPE descriptor [Ljava/lang/Class; flags 19 deprecated true signature [Ljava/lang/Class<*>; runtimeAnnotations @Ljava/lang/Deprecated; +field name inputTypes descriptor [Ljava/lang/Class; flags 4 signature [Ljava/lang/Class<*>; method name descriptor (Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Class;[Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)V flags 1 signature (Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Class<*>;[Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)V method name getInputTypes descriptor ()[Ljava/lang/Class; flags 1 signature ()[Ljava/lang/Class<*>; @@ -2042,10 +2042,10 @@ innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang class name javax/imageio/spi/ImageWriterSpi -field name STANDARD_OUTPUT_TYPE descriptor [Ljava/lang/Class; -field name outputTypes descriptor [Ljava/lang/Class; -field name STANDARD_OUTPUT_TYPE descriptor [Ljava/lang/Class; flags 19 deprecated true signature [Ljava/lang/Class<*>; runtimeAnnotations @Ljava/lang/Deprecated; -field name outputTypes descriptor [Ljava/lang/Class; flags 4 signature [Ljava/lang/Class<*>; -method name descriptor (Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Class;[Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)V -method name getOutputTypes descriptor ()[Ljava/lang/Class; +field name STANDARD_OUTPUT_TYPE descriptor [Ljava/lang/Class; flags 19 deprecated true signature [Ljava/lang/Class<*>; runtimeAnnotations @Ljava/lang/Deprecated; +field name outputTypes descriptor [Ljava/lang/Class; flags 4 signature [Ljava/lang/Class<*>; method name descriptor (Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Class;[Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)V flags 1 signature (Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;[Ljava/lang/Class<*>;[Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)V method name getOutputTypes descriptor ()[Ljava/lang/Class; flags 1 signature ()[Ljava/lang/Class<*>; @@ -3485,7 +3485,6 @@ innerclass innerClass javax/swing/JSpinner$NumberEditor outerClass javax/swing/J innerclass innerClass javax/swing/JSpinner$DefaultEditor outerClass javax/swing/JSpinner innerClassName DefaultEditor flags 9 innerclass innerClass javax/swing/JFormattedTextField$AbstractFormatter outerClass javax/swing/JFormattedTextField innerClassName AbstractFormatter flags 409 innerclass innerClass javax/swing/JFormattedTextField$AbstractFormatterFactory outerClass javax/swing/JFormattedTextField innerClassName AbstractFormatterFactory flags 409 -method name setComponentOrientation descriptor (Ljava/awt/ComponentOrientation;)V flags 1 class name javax/swing/JSplitPane header extends javax/swing/JComponent implements javax/accessibility/Accessible flags 21 runtimeAnnotations @Ljava/beans/JavaBean;(defaultProperty="UI") @@ -3592,8 +3591,6 @@ innerclass innerClass javax/swing/UIDefaults$LazyValue outerClass javax/swing/UI innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 -field name defaultRenderersByColumnClass descriptor Ljava/util/Hashtable; -field name defaultEditorsByColumnClass descriptor Ljava/util/Hashtable; -field name defaultRenderersByColumnClass descriptor Ljava/util/Hashtable; flags 84 signature Ljava/util/Hashtable; -field name defaultEditorsByColumnClass descriptor Ljava/util/Hashtable; flags 84 signature Ljava/util/Hashtable; -method name descriptor (Ljava/util/Vector;Ljava/util/Vector;)V -method name setTableHeader descriptor (Ljavax/swing/table/JTableHeader;)V -method name setRowHeight descriptor (I)V @@ -3638,6 +3635,8 @@ field name defaultEditorsByColumnClass descriptor Ljava/util/Hashtable; flags 84 -method name setFillsViewportHeight descriptor (Z)V -method name setCellEditor descriptor (Ljavax/swing/table/TableCellEditor;)V -method name getAccessibleContext descriptor ()Ljavax/accessibility/AccessibleContext; +field name defaultRenderersByColumnClass descriptor Ljava/util/Hashtable; flags 84 signature Ljava/util/Hashtable; +field name defaultEditorsByColumnClass descriptor Ljava/util/Hashtable; flags 84 signature Ljava/util/Hashtable; method name descriptor (Ljava/util/Vector;Ljava/util/Vector;)V flags 1 signature (Ljava/util/Vector<+Ljava/util/Vector;>;Ljava/util/Vector<*>;)V method name setTableHeader descriptor (Ljavax/swing/table/JTableHeader;)V flags 1 runtimeAnnotations @Ljava/beans/BeanProperty;(description="The\u005C;u0020;JTableHeader\u005C;u0020;instance\u005C;u0020;which\u005C;u0020;renders\u005C;u0020;the\u005C;u0020;column\u005C;u0020;headers.") method name setRowHeight descriptor (I)V flags 1 runtimeAnnotations @Ljava/beans/BeanProperty;(description="The\u005C;u0020;height\u005C;u0020;of\u005C;u0020;the\u005C;u0020;specified\u005C;u0020;row.") @@ -4230,12 +4229,12 @@ innerclass innerClass javax/swing/plaf/basic/BasicComboBoxRenderer$UIResource ou innerclass innerClass javax/swing/plaf/basic/BasicComboBoxEditor$UIResource outerClass javax/swing/plaf/basic/BasicComboBoxEditor innerClassName UIResource flags 9 -field name comboBox descriptor Ljavax/swing/JComboBox; -field name listBox descriptor Ljavax/swing/JList; -field name comboBox descriptor Ljavax/swing/JComboBox; flags 4 signature Ljavax/swing/JComboBox; -field name listBox descriptor Ljavax/swing/JList; flags 4 signature Ljavax/swing/JList; -method name createRenderer descriptor ()Ljavax/swing/ListCellRenderer; -method name isPopupVisible descriptor (Ljavax/swing/JComboBox;)Z -method name setPopupVisible descriptor (Ljavax/swing/JComboBox;Z)V -method name isFocusTraversable descriptor (Ljavax/swing/JComboBox;)Z +field name comboBox descriptor Ljavax/swing/JComboBox; flags 4 signature Ljavax/swing/JComboBox; +field name listBox descriptor Ljavax/swing/JList; flags 4 signature Ljavax/swing/JList; method name createRenderer descriptor ()Ljavax/swing/ListCellRenderer; flags 4 signature ()Ljavax/swing/ListCellRenderer; method name isPopupVisible descriptor (Ljavax/swing/JComboBox;)Z flags 1 signature (Ljavax/swing/JComboBox<*>;)Z method name setPopupVisible descriptor (Ljavax/swing/JComboBox;Z)V flags 1 signature (Ljavax/swing/JComboBox<*>;Z)V @@ -4254,13 +4253,13 @@ innerclass innerClass javax/swing/plaf/basic/BasicComboPopup$InvocationMouseMoti innerclass innerClass javax/swing/plaf/basic/BasicComboPopup$InvocationMouseHandler outerClass javax/swing/plaf/basic/BasicComboPopup innerClassName InvocationMouseHandler flags 4 -field name comboBox descriptor Ljavax/swing/JComboBox; -field name list descriptor Ljavax/swing/JList; -field name comboBox descriptor Ljavax/swing/JComboBox; flags 4 signature Ljavax/swing/JComboBox; -field name list descriptor Ljavax/swing/JList; flags 4 signature Ljavax/swing/JList; -method name getList descriptor ()Ljavax/swing/JList; -method name uninstallComboBoxModelListeners descriptor (Ljavax/swing/ComboBoxModel;)V -method name descriptor (Ljavax/swing/JComboBox;)V -method name createList descriptor ()Ljavax/swing/JList; -method name installComboBoxModelListeners descriptor (Ljavax/swing/ComboBoxModel;)V +field name comboBox descriptor Ljavax/swing/JComboBox; flags 4 signature Ljavax/swing/JComboBox; +field name list descriptor Ljavax/swing/JList; flags 4 signature Ljavax/swing/JList; method name getList descriptor ()Ljavax/swing/JList; flags 1 signature ()Ljavax/swing/JList; method name uninstallComboBoxModelListeners descriptor (Ljavax/swing/ComboBoxModel;)V flags 4 signature (Ljavax/swing/ComboBoxModel<*>;)V method name descriptor (Ljavax/swing/JComboBox;)V flags 1 signature (Ljavax/swing/JComboBox;)V @@ -4357,11 +4356,11 @@ innerclass innerClass javax/swing/plaf/basic/BasicListUI$MouseInputHandler outer innerclass innerClass javax/swing/JList$DropLocation outerClass javax/swing/JList innerClassName DropLocation flags 19 innerclass innerClass java/awt/Component$BaselineResizeBehavior outerClass java/awt/Component innerClassName BaselineResizeBehavior flags 4019 -field name list descriptor Ljavax/swing/JList; -field name list descriptor Ljavax/swing/JList; flags 4 signature Ljavax/swing/JList; -method name paintCell descriptor (Ljava/awt/Graphics;ILjava/awt/Rectangle;Ljavax/swing/ListCellRenderer;Ljavax/swing/ListModel;Ljavax/swing/ListSelectionModel;I)V -method name locationToIndex descriptor (Ljavax/swing/JList;Ljava/awt/Point;)I -method name indexToLocation descriptor (Ljavax/swing/JList;I)Ljava/awt/Point; -method name getCellBounds descriptor (Ljavax/swing/JList;II)Ljava/awt/Rectangle; +field name list descriptor Ljavax/swing/JList; flags 4 signature Ljavax/swing/JList; method name paintCell descriptor (Ljava/awt/Graphics;ILjava/awt/Rectangle;Ljavax/swing/ListCellRenderer;Ljavax/swing/ListModel;Ljavax/swing/ListSelectionModel;I)V flags 4 signature (Ljava/awt/Graphics;ILjava/awt/Rectangle;Ljavax/swing/ListCellRenderer;Ljavax/swing/ListModel;Ljavax/swing/ListSelectionModel;I)V method name locationToIndex descriptor (Ljavax/swing/JList;Ljava/awt/Point;)I flags 1 signature (Ljavax/swing/JList<*>;Ljava/awt/Point;)I method name indexToLocation descriptor (Ljavax/swing/JList;I)Ljava/awt/Point; flags 1 signature (Ljavax/swing/JList<*>;I)Ljava/awt/Point; @@ -4615,12 +4614,12 @@ innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang class name javax/swing/plaf/metal/MetalComboBoxButton -field name comboBox descriptor Ljavax/swing/JComboBox; -field name listBox descriptor Ljavax/swing/JList; -field name comboBox descriptor Ljavax/swing/JComboBox; flags 4 signature Ljavax/swing/JComboBox; -field name listBox descriptor Ljavax/swing/JList; flags 4 signature Ljavax/swing/JList; -method name getComboBox descriptor ()Ljavax/swing/JComboBox; -method name setComboBox descriptor (Ljavax/swing/JComboBox;)V -method name descriptor (Ljavax/swing/JComboBox;Ljavax/swing/Icon;Ljavax/swing/CellRendererPane;Ljavax/swing/JList;)V -method name descriptor (Ljavax/swing/JComboBox;Ljavax/swing/Icon;ZLjavax/swing/CellRendererPane;Ljavax/swing/JList;)V +field name comboBox descriptor Ljavax/swing/JComboBox; flags 4 signature Ljavax/swing/JComboBox; +field name listBox descriptor Ljavax/swing/JList; flags 4 signature Ljavax/swing/JList; method name getComboBox descriptor ()Ljavax/swing/JComboBox; flags 11 signature ()Ljavax/swing/JComboBox; method name setComboBox descriptor (Ljavax/swing/JComboBox;)V flags 11 signature (Ljavax/swing/JComboBox;)V method name descriptor (Ljavax/swing/JComboBox;Ljavax/swing/Icon;Ljavax/swing/CellRendererPane;Ljavax/swing/JList;)V flags 1 signature (Ljavax/swing/JComboBox;Ljavax/swing/Icon;Ljavax/swing/CellRendererPane;Ljavax/swing/JList;)V @@ -4740,10 +4739,10 @@ field name uis descriptor Ljava/util/Vector; flags 4 signature Ljava/util/Vector class name javax/swing/plaf/multi/MultiComboBoxUI -field name uis descriptor Ljava/util/Vector; -field name uis descriptor Ljava/util/Vector; flags 4 signature Ljava/util/Vector; -method name isFocusTraversable descriptor (Ljavax/swing/JComboBox;)Z -method name setPopupVisible descriptor (Ljavax/swing/JComboBox;Z)V -method name isPopupVisible descriptor (Ljavax/swing/JComboBox;)Z +field name uis descriptor Ljava/util/Vector; flags 4 signature Ljava/util/Vector; method name isFocusTraversable descriptor (Ljavax/swing/JComboBox;)Z flags 1 signature (Ljavax/swing/JComboBox<*>;)Z method name setPopupVisible descriptor (Ljavax/swing/JComboBox;Z)V flags 1 signature (Ljavax/swing/JComboBox<*>;Z)V method name isPopupVisible descriptor (Ljavax/swing/JComboBox;)Z flags 1 signature (Ljavax/swing/JComboBox<*>;)Z @@ -4770,10 +4769,10 @@ field name uis descriptor Ljava/util/Vector; flags 4 signature Ljava/util/Vector class name javax/swing/plaf/multi/MultiListUI -field name uis descriptor Ljava/util/Vector; -field name uis descriptor Ljava/util/Vector; flags 4 signature Ljava/util/Vector; -method name locationToIndex descriptor (Ljavax/swing/JList;Ljava/awt/Point;)I -method name indexToLocation descriptor (Ljavax/swing/JList;I)Ljava/awt/Point; -method name getCellBounds descriptor (Ljavax/swing/JList;II)Ljava/awt/Rectangle; +field name uis descriptor Ljava/util/Vector; flags 4 signature Ljava/util/Vector; method name locationToIndex descriptor (Ljavax/swing/JList;Ljava/awt/Point;)I flags 1 signature (Ljavax/swing/JList<*>;Ljava/awt/Point;)I method name indexToLocation descriptor (Ljavax/swing/JList;I)Ljava/awt/Point; flags 1 signature (Ljavax/swing/JList<*>;I)Ljava/awt/Point; method name getCellBounds descriptor (Ljavax/swing/JList;II)Ljava/awt/Rectangle; flags 1 signature (Ljavax/swing/JList<*>;II)Ljava/awt/Rectangle; @@ -4852,11 +4851,11 @@ field name uis descriptor Ljava/util/Vector; flags 4 signature Ljava/util/Vector class name javax/swing/plaf/multi/MultiTextUI -field name uis descriptor Ljava/util/Vector; -field name uis descriptor Ljava/util/Vector; flags 4 signature Ljava/util/Vector; -method name modelToView descriptor (Ljavax/swing/text/JTextComponent;I)Ljava/awt/Rectangle; -method name modelToView descriptor (Ljavax/swing/text/JTextComponent;ILjavax/swing/text/Position$Bias;)Ljava/awt/Rectangle; -method name viewToModel descriptor (Ljavax/swing/text/JTextComponent;Ljava/awt/Point;)I -method name viewToModel descriptor (Ljavax/swing/text/JTextComponent;Ljava/awt/Point;[Ljavax/swing/text/Position$Bias;)I +field name uis descriptor Ljava/util/Vector; flags 4 signature Ljava/util/Vector; method name modelToView descriptor (Ljavax/swing/text/JTextComponent;I)Ljava/awt/Rectangle; thrownTypes javax/swing/text/BadLocationException flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") method name modelToView descriptor (Ljavax/swing/text/JTextComponent;ILjavax/swing/text/Position$Bias;)Ljava/awt/Rectangle; thrownTypes javax/swing/text/BadLocationException flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") method name modelToView2D descriptor (Ljavax/swing/text/JTextComponent;ILjavax/swing/text/Position$Bias;)Ljava/awt/geom/Rectangle2D; thrownTypes javax/swing/text/BadLocationException flags 1 @@ -4982,7 +4981,6 @@ innerclass innerClass javax/swing/JTable$DropLocation outerClass javax/swing/JTa class name javax/swing/table/DefaultTableModel -field name dataVector descriptor Ljava/util/Vector; -field name dataVector descriptor Ljava/util/Vector; flags 4 signature Ljava/util/Vector; -method name descriptor (Ljava/util/Vector;I)V -method name descriptor (Ljava/util/Vector;Ljava/util/Vector;)V -method name getDataVector descriptor ()Ljava/util/Vector; @@ -4993,6 +4991,7 @@ field name dataVector descriptor Ljava/util/Vector; flags 4 signature Ljava/util -method name addColumn descriptor (Ljava/lang/Object;Ljava/util/Vector;)V -method name convertToVector descriptor ([Ljava/lang/Object;)Ljava/util/Vector; -method name convertToVector descriptor ([[Ljava/lang/Object;)Ljava/util/Vector; +field name dataVector descriptor Ljava/util/Vector; flags 4 signature Ljava/util/Vector; method name descriptor (Ljava/util/Vector;I)V flags 1 signature (Ljava/util/Vector<*>;I)V method name descriptor (Ljava/util/Vector;Ljava/util/Vector;)V flags 1 signature (Ljava/util/Vector<+Ljava/util/Vector;>;Ljava/util/Vector<*>;)V method name getDataVector descriptor ()Ljava/util/Vector; flags 1 signature ()Ljava/util/Vector; @@ -5832,13 +5831,13 @@ class name javax/swing/tree/DefaultMutableTreeNode header extends java/lang/Object implements java/lang/Cloneable,javax/swing/tree/MutableTreeNode,java/io/Serializable flags 21 innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 -field name children descriptor Ljava/util/Vector; -field name children descriptor Ljava/util/Vector; flags 4 signature Ljava/util/Vector; -method name children descriptor ()Ljava/util/Enumeration; -method name preorderEnumeration descriptor ()Ljava/util/Enumeration; -method name postorderEnumeration descriptor ()Ljava/util/Enumeration; -method name breadthFirstEnumeration descriptor ()Ljava/util/Enumeration; -method name depthFirstEnumeration descriptor ()Ljava/util/Enumeration; -method name pathFromAncestorEnumeration descriptor (Ljavax/swing/tree/TreeNode;)Ljava/util/Enumeration; +field name children descriptor Ljava/util/Vector; flags 4 signature Ljava/util/Vector; method name children descriptor ()Ljava/util/Enumeration; flags 1 signature ()Ljava/util/Enumeration; method name preorderEnumeration descriptor ()Ljava/util/Enumeration; flags 1 signature ()Ljava/util/Enumeration; method name postorderEnumeration descriptor ()Ljava/util/Enumeration; flags 1 signature ()Ljava/util/Enumeration; diff --git a/src/jdk.compiler/share/data/symbols/java.xml.bind-9.sym.txt b/src/jdk.compiler/share/data/symbols/java.xml.bind-9.sym.txt index f6c007544d9..f6a8ebd2f2c 100644 --- a/src/jdk.compiler/share/data/symbols/java.xml.bind-9.sym.txt +++ b/src/jdk.compiler/share/data/symbols/java.xml.bind-9.sym.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -35,10 +35,10 @@ innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang class name javax/xml/bind/JAXBContext -field name JAXB_CONTEXT_FACTORY descriptor Ljava/lang/String; -field name JAXB_CONTEXT_FACTORY descriptor Ljava/lang/String; constantValue javax.xml.bind.JAXBContextFactory flags 19 -method name newInstance descriptor ([Ljava/lang/Class;)Ljavax/xml/bind/JAXBContext; -method name newInstance descriptor ([Ljava/lang/Class;Ljava/util/Map;)Ljavax/xml/bind/JAXBContext; -method name createValidator descriptor ()Ljavax/xml/bind/Validator; +field name JAXB_CONTEXT_FACTORY descriptor Ljava/lang/String; constantValue javax.xml.bind.JAXBContextFactory flags 19 method name newInstance descriptor ([Ljava/lang/Class;)Ljavax/xml/bind/JAXBContext; thrownTypes javax/xml/bind/JAXBException flags 89 signature ([Ljava/lang/Class<*>;)Ljavax/xml/bind/JAXBContext; method name newInstance descriptor ([Ljava/lang/Class;Ljava/util/Map;)Ljavax/xml/bind/JAXBContext; thrownTypes javax/xml/bind/JAXBException flags 9 signature ([Ljava/lang/Class<*>;Ljava/util/Map;)Ljavax/xml/bind/JAXBContext; method name createValidator descriptor ()Ljavax/xml/bind/Validator; thrownTypes javax/xml/bind/JAXBException flags 401 deprecated true runtimeAnnotations @Ljava/lang/Deprecated; diff --git a/src/jdk.compiler/share/data/symbols/jdk.management-8.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.management-8.sym.txt index ac0bdef06ac..15811f99cb7 100644 --- a/src/jdk.compiler/share/data/symbols/jdk.management-8.sym.txt +++ b/src/jdk.compiler/share/data/symbols/jdk.management-8.sym.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -91,6 +91,10 @@ method name getThreadAllocatedBytes descriptor ([J)[J flags 401 method name isThreadAllocatedMemorySupported descriptor ()Z flags 401 method name isThreadAllocatedMemoryEnabled descriptor ()Z flags 401 method name setThreadAllocatedMemoryEnabled descriptor (Z)V flags 401 +method name getCurrentThreadAllocatedBytes descriptor ()J flags 1 +method name getTotalThreadAllocatedBytes descriptor ()J flags 1 +method name getThreadInfo descriptor ([JZZI)[Ljava/lang/management/ThreadInfo; flags 1 +method name dumpAllThreads descriptor (ZZI)[Ljava/lang/management/ThreadInfo; flags 1 class name com/sun/management/UnixOperatingSystemMXBean header extends java/lang/Object implements com/sun/management/OperatingSystemMXBean flags 601 classAnnotations @Ljdk/Profile+Annotation;(value=I3) runtimeAnnotations @Ljdk/Exported; diff --git a/src/jdk.compiler/share/data/symbols/jdk.management-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.management-9.sym.txt index 6df3114e44a..8ef9e4bb504 100644 --- a/src/jdk.compiler/share/data/symbols/jdk.management-9.sym.txt +++ b/src/jdk.compiler/share/data/symbols/jdk.management-9.sym.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -48,6 +48,10 @@ header extends java/lang/Object implements java/lang/management/OperatingSystemM class name com/sun/management/ThreadMXBean header extends java/lang/Object implements java/lang/management/ThreadMXBean flags 601 +-method name getCurrentThreadAllocatedBytes descriptor ()J +-method name getTotalThreadAllocatedBytes descriptor ()J +-method name getThreadInfo descriptor ([JZZI)[Ljava/lang/management/ThreadInfo; +-method name dumpAllThreads descriptor (ZZI)[Ljava/lang/management/ThreadInfo; class name com/sun/management/UnixOperatingSystemMXBean header extends java/lang/Object implements com/sun/management/OperatingSystemMXBean flags 601 diff --git a/src/jdk.compiler/share/data/symbols/jdk.net-8.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.net-8.sym.txt new file mode 100644 index 00000000000..a579e8f59ec --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/jdk.net-8.sym.txt @@ -0,0 +1,76 @@ +# +# Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name jdk/net/ExtendedSocketOptions +header extends java/lang/Object flags 31 classAnnotations @Ljdk/Profile+Annotation;(value=I1) runtimeAnnotations @Ljdk/Exported; +field name SO_FLOW_SLA descriptor Ljava/net/SocketOption; flags 19 signature Ljava/net/SocketOption; +field name TCP_KEEPIDLE descriptor Ljava/net/SocketOption; flags 19 signature Ljava/net/SocketOption; +field name TCP_KEEPINTERVAL descriptor Ljava/net/SocketOption; flags 19 signature Ljava/net/SocketOption; +field name TCP_KEEPCOUNT descriptor Ljava/net/SocketOption; flags 19 signature Ljava/net/SocketOption; + +class name jdk/net/NetworkPermission +header extends java/security/BasicPermission flags 31 classAnnotations @Ljdk/Profile+Annotation;(value=I1) runtimeAnnotations @Ljdk/Exported; +method name descriptor (Ljava/lang/String;)V flags 1 +method name descriptor (Ljava/lang/String;Ljava/lang/String;)V flags 1 + +class name jdk/net/SocketFlow +header extends java/lang/Object flags 21 classAnnotations @Ljdk/Profile+Annotation;(value=I1) runtimeAnnotations @Ljdk/Exported; +innerclass innerClass jdk/net/SocketFlow$Status outerClass jdk/net/SocketFlow innerClassName Status flags 4019 +field name NORMAL_PRIORITY descriptor I constantValue 1 flags 19 +field name HIGH_PRIORITY descriptor I constantValue 2 flags 19 +method name create descriptor ()Ljdk/net/SocketFlow; flags 9 +method name priority descriptor (I)Ljdk/net/SocketFlow; flags 1 +method name bandwidth descriptor (J)Ljdk/net/SocketFlow; flags 1 +method name priority descriptor ()I flags 1 +method name bandwidth descriptor ()J flags 1 +method name status descriptor ()Ljdk/net/SocketFlow$Status; flags 1 + +class name jdk/net/SocketFlow$Status +header extends java/lang/Enum flags 4031 signature Ljava/lang/Enum; runtimeAnnotations @Ljdk/Exported; +innerclass innerClass jdk/net/SocketFlow$Status outerClass jdk/net/SocketFlow innerClassName Status flags 4019 +field name NO_STATUS descriptor Ljdk/net/SocketFlow$Status; flags 4019 +field name OK descriptor Ljdk/net/SocketFlow$Status; flags 4019 +field name NO_PERMISSION descriptor Ljdk/net/SocketFlow$Status; flags 4019 +field name NOT_CONNECTED descriptor Ljdk/net/SocketFlow$Status; flags 4019 +field name NOT_SUPPORTED descriptor Ljdk/net/SocketFlow$Status; flags 4019 +field name ALREADY_CREATED descriptor Ljdk/net/SocketFlow$Status; flags 4019 +field name IN_PROGRESS descriptor Ljdk/net/SocketFlow$Status; flags 4019 +field name OTHER descriptor Ljdk/net/SocketFlow$Status; flags 4019 +method name values descriptor ()[Ljdk/net/SocketFlow$Status; flags 9 +method name valueOf descriptor (Ljava/lang/String;)Ljdk/net/SocketFlow$Status; flags 9 + +class name jdk/net/Sockets +header extends java/lang/Object flags 21 classAnnotations @Ljdk/Profile+Annotation;(value=I1) runtimeAnnotations @Ljdk/Exported; +method name setOption descriptor (Ljava/net/Socket;Ljava/net/SocketOption;Ljava/lang/Object;)V thrownTypes java/io/IOException flags 9 signature (Ljava/net/Socket;Ljava/net/SocketOption;TT;)V +method name getOption descriptor (Ljava/net/Socket;Ljava/net/SocketOption;)Ljava/lang/Object; thrownTypes java/io/IOException flags 9 signature (Ljava/net/Socket;Ljava/net/SocketOption;)TT; +method name setOption descriptor (Ljava/net/ServerSocket;Ljava/net/SocketOption;Ljava/lang/Object;)V thrownTypes java/io/IOException flags 9 signature (Ljava/net/ServerSocket;Ljava/net/SocketOption;TT;)V +method name getOption descriptor (Ljava/net/ServerSocket;Ljava/net/SocketOption;)Ljava/lang/Object; thrownTypes java/io/IOException flags 9 signature (Ljava/net/ServerSocket;Ljava/net/SocketOption;)TT; +method name setOption descriptor (Ljava/net/DatagramSocket;Ljava/net/SocketOption;Ljava/lang/Object;)V thrownTypes java/io/IOException flags 9 signature (Ljava/net/DatagramSocket;Ljava/net/SocketOption;TT;)V +method name getOption descriptor (Ljava/net/DatagramSocket;Ljava/net/SocketOption;)Ljava/lang/Object; thrownTypes java/io/IOException flags 9 signature (Ljava/net/DatagramSocket;Ljava/net/SocketOption;)TT; +method name supportedOptions descriptor (Ljava/lang/Class;)Ljava/util/Set; flags 9 signature (Ljava/lang/Class<*>;)Ljava/util/Set;>; + diff --git a/src/jdk.compiler/share/data/symbols/jdk.net-9.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.net-9.sym.txt index d52c33c546a..7db67409789 100644 --- a/src/jdk.compiler/share/data/symbols/jdk.net-9.sym.txt +++ b/src/jdk.compiler/share/data/symbols/jdk.net-9.sym.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -32,51 +32,26 @@ header exports jdk/net requires name\u0020;java.base\u0020;flags\u0020;8000 flag class name jdk/net/ExtendedSocketOptions header extends java/lang/Object flags 31 innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 -field name SO_FLOW_SLA descriptor Ljava/net/SocketOption; flags 19 signature Ljava/net/SocketOption; +-field name TCP_KEEPIDLE descriptor Ljava/net/SocketOption; +-field name TCP_KEEPINTERVAL descriptor Ljava/net/SocketOption; +-field name TCP_KEEPCOUNT descriptor Ljava/net/SocketOption; class name jdk/net/NetworkPermission header extends java/security/BasicPermission flags 31 -method name descriptor (Ljava/lang/String;)V flags 1 -method name descriptor (Ljava/lang/String;Ljava/lang/String;)V flags 1 class name jdk/net/SocketFlow header extends java/lang/Object flags 21 innerclass innerClass jdk/net/SocketFlow$Status outerClass jdk/net/SocketFlow innerClassName Status flags 4019 innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 field name UNSET descriptor I constantValue -1 flags 19 -field name NORMAL_PRIORITY descriptor I constantValue 1 flags 19 -field name HIGH_PRIORITY descriptor I constantValue 2 flags 19 -method name create descriptor ()Ljdk/net/SocketFlow; flags 9 -method name priority descriptor (I)Ljdk/net/SocketFlow; flags 1 -method name bandwidth descriptor (J)Ljdk/net/SocketFlow; flags 1 -method name priority descriptor ()I flags 1 -method name bandwidth descriptor ()J flags 1 -method name status descriptor ()Ljdk/net/SocketFlow$Status; flags 1 method name toString descriptor ()Ljava/lang/String; flags 1 class name jdk/net/SocketFlow$Status header extends java/lang/Enum flags 4031 signature Ljava/lang/Enum; innerclass innerClass jdk/net/SocketFlow$Status outerClass jdk/net/SocketFlow innerClassName Status flags 4019 innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 -field name NO_STATUS descriptor Ljdk/net/SocketFlow$Status; flags 4019 -field name OK descriptor Ljdk/net/SocketFlow$Status; flags 4019 -field name NO_PERMISSION descriptor Ljdk/net/SocketFlow$Status; flags 4019 -field name NOT_CONNECTED descriptor Ljdk/net/SocketFlow$Status; flags 4019 -field name NOT_SUPPORTED descriptor Ljdk/net/SocketFlow$Status; flags 4019 -field name ALREADY_CREATED descriptor Ljdk/net/SocketFlow$Status; flags 4019 -field name IN_PROGRESS descriptor Ljdk/net/SocketFlow$Status; flags 4019 -field name OTHER descriptor Ljdk/net/SocketFlow$Status; flags 4019 -method name values descriptor ()[Ljdk/net/SocketFlow$Status; flags 9 -method name valueOf descriptor (Ljava/lang/String;)Ljdk/net/SocketFlow$Status; flags 9 class name jdk/net/Sockets header extends java/lang/Object flags 21 innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 -method name setOption descriptor (Ljava/net/Socket;Ljava/net/SocketOption;Ljava/lang/Object;)V thrownTypes java/io/IOException flags 9 signature (Ljava/net/Socket;Ljava/net/SocketOption;TT;)V -method name getOption descriptor (Ljava/net/Socket;Ljava/net/SocketOption;)Ljava/lang/Object; thrownTypes java/io/IOException flags 9 signature (Ljava/net/Socket;Ljava/net/SocketOption;)TT; -method name setOption descriptor (Ljava/net/ServerSocket;Ljava/net/SocketOption;Ljava/lang/Object;)V thrownTypes java/io/IOException flags 9 signature (Ljava/net/ServerSocket;Ljava/net/SocketOption;TT;)V -method name getOption descriptor (Ljava/net/ServerSocket;Ljava/net/SocketOption;)Ljava/lang/Object; thrownTypes java/io/IOException flags 9 signature (Ljava/net/ServerSocket;Ljava/net/SocketOption;)TT; -method name setOption descriptor (Ljava/net/DatagramSocket;Ljava/net/SocketOption;Ljava/lang/Object;)V thrownTypes java/io/IOException flags 9 signature (Ljava/net/DatagramSocket;Ljava/net/SocketOption;TT;)V -method name getOption descriptor (Ljava/net/DatagramSocket;Ljava/net/SocketOption;)Ljava/lang/Object; thrownTypes java/io/IOException flags 9 signature (Ljava/net/DatagramSocket;Ljava/net/SocketOption;)TT; -method name supportedOptions descriptor (Ljava/lang/Class;)Ljava/util/Set; flags 9 signature (Ljava/lang/Class<*>;)Ljava/util/Set;>; diff --git a/src/jdk.compiler/share/data/symbols/symbols b/src/jdk.compiler/share/data/symbols/symbols index 7793033d22f..34619bed887 100644 --- a/src/jdk.compiler/share/data/symbols/symbols +++ b/src/jdk.compiler/share/data/symbols/symbols @@ -30,7 +30,7 @@ #build.tools.symbolgenerator.CreateSymbols build-description-incremental symbols include.list # generate platforms 8:9:A:B:C:D:E:F:G:H:I:J:K:L:M:N:O:P -platform version 8 files java.activation-8.sym.txt:java.base-8.sym.txt:java.compiler-8.sym.txt:java.corba-8.sym.txt:java.datatransfer-8.sym.txt:java.desktop-8.sym.txt:java.instrument-8.sym.txt:java.logging-8.sym.txt:java.management-8.sym.txt:java.management.rmi-8.sym.txt:java.naming-8.sym.txt:java.prefs-8.sym.txt:java.rmi-8.sym.txt:java.scripting-8.sym.txt:java.security.jgss-8.sym.txt:java.security.sasl-8.sym.txt:java.sql-8.sym.txt:java.sql.rowset-8.sym.txt:java.transaction-8.sym.txt:java.xml-8.sym.txt:java.xml.bind-8.sym.txt:java.xml.crypto-8.sym.txt:java.xml.ws-8.sym.txt:java.xml.ws.annotation-8.sym.txt:jdk.httpserver-8.sym.txt:jdk.management-8.sym.txt:jdk.scripting.nashorn-8.sym.txt:jdk.sctp-8.sym.txt:jdk.security.auth-8.sym.txt:jdk.security.jgss-8.sym.txt +platform version 8 files java.activation-8.sym.txt:java.base-8.sym.txt:java.compiler-8.sym.txt:java.corba-8.sym.txt:java.datatransfer-8.sym.txt:java.desktop-8.sym.txt:java.instrument-8.sym.txt:java.logging-8.sym.txt:java.management-8.sym.txt:java.management.rmi-8.sym.txt:java.naming-8.sym.txt:java.prefs-8.sym.txt:java.rmi-8.sym.txt:java.scripting-8.sym.txt:java.security.jgss-8.sym.txt:java.security.sasl-8.sym.txt:java.sql-8.sym.txt:java.sql.rowset-8.sym.txt:java.transaction-8.sym.txt:java.xml-8.sym.txt:java.xml.bind-8.sym.txt:java.xml.crypto-8.sym.txt:java.xml.ws-8.sym.txt:java.xml.ws.annotation-8.sym.txt:jdk.httpserver-8.sym.txt:jdk.management-8.sym.txt:jdk.net-8.sym.txt:jdk.scripting.nashorn-8.sym.txt:jdk.sctp-8.sym.txt:jdk.security.auth-8.sym.txt:jdk.security.jgss-8.sym.txt platform version 9 base 8 files java.activation-9.sym.txt:java.base-9.sym.txt:java.compiler-9.sym.txt:java.corba-9.sym.txt:java.datatransfer-9.sym.txt:java.desktop-9.sym.txt:java.instrument-9.sym.txt:java.logging-9.sym.txt:java.management-9.sym.txt:java.management.rmi-9.sym.txt:java.naming-9.sym.txt:java.prefs-9.sym.txt:java.rmi-9.sym.txt:java.scripting-9.sym.txt:java.se-9.sym.txt:java.se.ee-9.sym.txt:java.security.jgss-9.sym.txt:java.security.sasl-9.sym.txt:java.smartcardio-9.sym.txt:java.sql-9.sym.txt:java.sql.rowset-9.sym.txt:java.transaction-9.sym.txt:java.xml-9.sym.txt:java.xml.bind-9.sym.txt:java.xml.crypto-9.sym.txt:java.xml.ws-9.sym.txt:java.xml.ws.annotation-9.sym.txt:jdk.accessibility-9.sym.txt:jdk.attach-9.sym.txt:jdk.charsets-9.sym.txt:jdk.compiler-9.sym.txt:jdk.crypto.cryptoki-9.sym.txt:jdk.crypto.ec-9.sym.txt:jdk.dynalink-9.sym.txt:jdk.editpad-9.sym.txt:jdk.hotspot.agent-9.sym.txt:jdk.httpserver-9.sym.txt:jdk.incubator.httpclient-9.sym.txt:jdk.jartool-9.sym.txt:jdk.javadoc-9.sym.txt:jdk.jcmd-9.sym.txt:jdk.jconsole-9.sym.txt:jdk.jdeps-9.sym.txt:jdk.jdi-9.sym.txt:jdk.jdwp.agent-9.sym.txt:jdk.jlink-9.sym.txt:jdk.jshell-9.sym.txt:jdk.jsobject-9.sym.txt:jdk.jstatd-9.sym.txt:jdk.localedata-9.sym.txt:jdk.management-9.sym.txt:jdk.management.agent-9.sym.txt:jdk.naming.dns-9.sym.txt:jdk.naming.rmi-9.sym.txt:jdk.net-9.sym.txt:jdk.pack-9.sym.txt:jdk.policytool-9.sym.txt:jdk.rmic-9.sym.txt:jdk.scripting.nashorn-9.sym.txt:jdk.sctp-9.sym.txt:jdk.security.auth-9.sym.txt:jdk.security.jgss-9.sym.txt:jdk.unsupported-9.sym.txt:jdk.xml.dom-9.sym.txt:jdk.zipfs-9.sym.txt platform version A base 9 files java.activation-A.sym.txt:java.base-A.sym.txt:java.compiler-A.sym.txt:java.corba-A.sym.txt:java.datatransfer-A.sym.txt:java.desktop-A.sym.txt:java.instrument-A.sym.txt:java.logging-A.sym.txt:java.management-A.sym.txt:java.management.rmi-A.sym.txt:java.naming-A.sym.txt:java.prefs-A.sym.txt:java.rmi-A.sym.txt:java.scripting-A.sym.txt:java.se-A.sym.txt:java.se.ee-A.sym.txt:java.security.jgss-A.sym.txt:java.security.sasl-A.sym.txt:java.smartcardio-A.sym.txt:java.sql-A.sym.txt:java.sql.rowset-A.sym.txt:java.transaction-A.sym.txt:java.xml-A.sym.txt:java.xml.bind-A.sym.txt:java.xml.crypto-A.sym.txt:java.xml.ws-A.sym.txt:java.xml.ws.annotation-A.sym.txt:jdk.accessibility-A.sym.txt:jdk.attach-A.sym.txt:jdk.charsets-A.sym.txt:jdk.compiler-A.sym.txt:jdk.crypto.cryptoki-A.sym.txt:jdk.crypto.ec-A.sym.txt:jdk.dynalink-A.sym.txt:jdk.editpad-A.sym.txt:jdk.hotspot.agent-A.sym.txt:jdk.httpserver-A.sym.txt:jdk.incubator.httpclient-A.sym.txt:jdk.jartool-A.sym.txt:jdk.javadoc-A.sym.txt:jdk.jcmd-A.sym.txt:jdk.jconsole-A.sym.txt:jdk.jdeps-A.sym.txt:jdk.jdi-A.sym.txt:jdk.jdwp.agent-A.sym.txt:jdk.jlink-A.sym.txt:jdk.jshell-A.sym.txt:jdk.jsobject-A.sym.txt:jdk.jstatd-A.sym.txt:jdk.localedata-A.sym.txt:jdk.management-A.sym.txt:jdk.management.agent-A.sym.txt:jdk.naming.dns-A.sym.txt:jdk.naming.rmi-A.sym.txt:jdk.net-A.sym.txt:jdk.pack-A.sym.txt:jdk.policytool-A.sym.txt:jdk.rmic-A.sym.txt:jdk.scripting.nashorn-A.sym.txt:jdk.sctp-A.sym.txt:jdk.security.auth-A.sym.txt:jdk.security.jgss-A.sym.txt:jdk.unsupported-A.sym.txt:jdk.xml.dom-A.sym.txt:jdk.zipfs-A.sym.txt platform version B base A files java.activation-B.sym.txt:java.base-B.sym.txt:java.compiler-B.sym.txt:java.corba-B.sym.txt:java.datatransfer-B.sym.txt:java.desktop-B.sym.txt:java.instrument-B.sym.txt:java.logging-B.sym.txt:java.management-B.sym.txt:java.management.rmi-B.sym.txt:java.naming-B.sym.txt:java.net.http-B.sym.txt:java.prefs-B.sym.txt:java.rmi-B.sym.txt:java.scripting-B.sym.txt:java.se-B.sym.txt:java.se.ee-B.sym.txt:java.security.jgss-B.sym.txt:java.security.sasl-B.sym.txt:java.smartcardio-B.sym.txt:java.sql-B.sym.txt:java.sql.rowset-B.sym.txt:java.transaction-B.sym.txt:java.transaction.xa-B.sym.txt:java.xml-B.sym.txt:java.xml.bind-B.sym.txt:java.xml.crypto-B.sym.txt:java.xml.ws-B.sym.txt:java.xml.ws.annotation-B.sym.txt:jdk.accessibility-B.sym.txt:jdk.attach-B.sym.txt:jdk.charsets-B.sym.txt:jdk.compiler-B.sym.txt:jdk.crypto.cryptoki-B.sym.txt:jdk.crypto.ec-B.sym.txt:jdk.dynalink-B.sym.txt:jdk.editpad-B.sym.txt:jdk.hotspot.agent-B.sym.txt:jdk.httpserver-B.sym.txt:jdk.incubator.httpclient-B.sym.txt:jdk.jartool-B.sym.txt:jdk.javadoc-B.sym.txt:jdk.jcmd-B.sym.txt:jdk.jconsole-B.sym.txt:jdk.jdeps-B.sym.txt:jdk.jdi-B.sym.txt:jdk.jdwp.agent-B.sym.txt:jdk.jfr-B.sym.txt:jdk.jlink-B.sym.txt:jdk.jshell-B.sym.txt:jdk.jsobject-B.sym.txt:jdk.jstatd-B.sym.txt:jdk.localedata-B.sym.txt:jdk.management-B.sym.txt:jdk.management.agent-B.sym.txt:jdk.management.jfr-B.sym.txt:jdk.naming.dns-B.sym.txt:jdk.naming.rmi-B.sym.txt:jdk.net-B.sym.txt:jdk.pack-B.sym.txt:jdk.rmic-B.sym.txt:jdk.scripting.nashorn-B.sym.txt:jdk.sctp-B.sym.txt:jdk.security.auth-B.sym.txt:jdk.security.jgss-B.sym.txt:jdk.unsupported-B.sym.txt:jdk.xml.dom-B.sym.txt:jdk.zipfs-B.sym.txt diff --git a/test/langtools/tools/javac/platform/CompilationTest.java b/test/langtools/tools/javac/platform/CompilationTest.java new file mode 100644 index 00000000000..93fb2fb2678 --- /dev/null +++ b/test/langtools/tools/javac/platform/CompilationTest.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8365060 + * @summary Verify javac can compile given snippets with --release + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.platform + * jdk.compiler/com.sun.tools.javac.util:+open + * @build toolbox.ToolBox CompilationTest + * @run main CompilationTest + */ + +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import toolbox.JavacTask; +import toolbox.Task; +import toolbox.ToolBox; + +public class CompilationTest { + + private final ToolBox tb = new ToolBox(); + public static void main(String... args) throws IOException, URISyntaxException { + CompilationTest t = new CompilationTest(); + + t.testJdkNet(); + } + + void testJdkNet() throws IOException { + Path root = Paths.get("."); + Path classes = root.resolve("classes"); + Files.createDirectories(classes); + + new JavacTask(tb) + .outdir(classes) + .options("--release", "8", + "-XDrawDiagnostics") + .sources(""" + import jdk.net.ExtendedSocketOptions; + public class Test { + } + """) + .run() + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + } + +} diff --git a/test/langtools/tools/javac/sym/ElementStructureTest.java b/test/langtools/tools/javac/sym/ElementStructureTest.java index f1cc3cd91fe..14fa194501a 100644 --- a/test/langtools/tools/javac/sym/ElementStructureTest.java +++ b/test/langtools/tools/javac/sym/ElementStructureTest.java @@ -132,10 +132,10 @@ public class ElementStructureTest { (byte) 0x3D, (byte) 0xC1, (byte) 0xFE, (byte) 0xCB }; static final byte[] hash8 = new byte[] { - (byte) 0x10, (byte) 0xE6, (byte) 0xE8, (byte) 0x11, - (byte) 0xC8, (byte) 0x02, (byte) 0x63, (byte) 0x9B, - (byte) 0xAB, (byte) 0x11, (byte) 0x9E, (byte) 0x4F, - (byte) 0xFA, (byte) 0x00, (byte) 0x6D, (byte) 0x81 + (byte) 0x07, (byte) 0xAB, (byte) 0x0A, (byte) 0x8D, + (byte) 0x1C, (byte) 0x44, (byte) 0x6D, (byte) 0x71, + (byte) 0x07, (byte) 0x53, (byte) 0x59, (byte) 0x74, + (byte) 0x5B, (byte) 0x49, (byte) 0x60, (byte) 0xAD }; final static Map version2Hash = new HashMap<>(); @@ -283,7 +283,7 @@ public class ElementStructureTest { } JavaFileObject file = new ByteArrayJavaFileObject(data.toByteArray()); try (InputStream in = new ByteArrayInputStream(data.toByteArray())) { - String name = ClassFile.of().parse(in.readAllBytes()).thisClass().name().stringValue(); + String name = ClassFile.of().parse(in.readAllBytes()).thisClass().name().stringValue().replace("/", "."); className2File.put(name, file); file2ClassName.put(file, name); } catch (IOException ex) { @@ -514,6 +514,8 @@ public class ElementStructureTest { out.write(Double.toHexString((Double) value)); } else if (value instanceof Float) { out.write(Float.toHexString((Float) value)); + } else if (value instanceof Character ch && Character.isSurrogate(ch)) { + out.write(Integer.toHexString(ch)); } else { out.write(String.valueOf(value)); } From 444007fc234aeff75025831c2d1b5538c87fa8f1 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Tue, 30 Sep 2025 12:27:22 +0000 Subject: [PATCH 0005/1639] 8368842: Parallel: Refactor PCAddThreadRootsMarkingTaskClosure Reviewed-by: fandreuzzi, tschatzl --- .../share/gc/parallel/psParallelCompact.cpp | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.cpp b/src/hotspot/share/gc/parallel/psParallelCompact.cpp index 484533619a4..af812c652a6 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp @@ -1053,24 +1053,19 @@ bool PSParallelCompact::invoke(bool clear_all_soft_refs, bool should_do_max_comp } class PCAddThreadRootsMarkingTaskClosure : public ThreadClosure { -private: - uint _worker_id; + ParCompactionManager* _cm; public: - PCAddThreadRootsMarkingTaskClosure(uint worker_id) : _worker_id(worker_id) { } + PCAddThreadRootsMarkingTaskClosure(ParCompactionManager* cm) : _cm(cm) { } void do_thread(Thread* thread) { - assert(ParallelScavengeHeap::heap()->is_stw_gc_active(), "called outside gc"); - ResourceMark rm; - ParCompactionManager* cm = ParCompactionManager::gc_thread_compaction_manager(_worker_id); + MarkingNMethodClosure mark_and_push_in_blobs(&_cm->_mark_and_push_closure); - MarkingNMethodClosure mark_and_push_in_blobs(&cm->_mark_and_push_closure); - - thread->oops_do(&cm->_mark_and_push_closure, &mark_and_push_in_blobs); + thread->oops_do(&_cm->_mark_and_push_closure, &mark_and_push_in_blobs); // Do the real work - cm->follow_marking_stacks(); + _cm->follow_marking_stacks(); } }; @@ -1114,7 +1109,7 @@ public: } { - PCAddThreadRootsMarkingTaskClosure closure(worker_id); + PCAddThreadRootsMarkingTaskClosure closure(cm); Threads::possibly_parallel_threads_do(_active_workers > 1 /* is_par */, &closure); } From 07ea907e4fc8aa8fda01d8fe64c599f9d944eef9 Mon Sep 17 00:00:00 2001 From: Anass Baya Date: Tue, 30 Sep 2025 13:57:07 +0000 Subject: [PATCH 0006/1639] 8361606: ConsumeNextMnemonicKeyTypedTest.java fails on Windows: character typed with VK_A: a 8321303: Intermittent open/test/jdk/java/awt/KeyboardFocusmanager/ConsumeNextMnemonicKeyTypedTest/ConsumeNextMnemonicKeyTypedTest.java failure on Linux Reviewed-by: dnguyen, honkar, aivanov --- .../classes/javax/swing/plaf/basic/BasicPopupMenuUI.java | 3 ++- test/jdk/ProblemList.txt | 1 - .../ConsumeNextMnemonicKeyTypedTest.java | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPopupMenuUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPopupMenuUI.java index e518f509c5a..6fab795e36c 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPopupMenuUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicPopupMenuUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -377,6 +377,7 @@ public class BasicPopupMenuUI extends PopupMenuUI { } else if (item.isEnabled()) { // we have a menu item manager.clearSelectedPath(); + sun.awt.SunToolkit.consumeNextKeyTyped(e); item.doClick(); } e.consume(); diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 381c0c8b0be..1602baa9894 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -487,7 +487,6 @@ java/awt/Graphics2D/DrawString/RotTransText.java 8316878 linux-all java/awt/KeyboardFocusmanager/TypeAhead/ButtonActionKeyTest/ButtonActionKeyTest.java 8257529 windows-x64 java/awt/KeyboardFocusmanager/ConsumeNextMnemonicKeyTypedTest/ConsumeForModalDialogTest/ConsumeForModalDialogTest.java 8302787 windows-all java/awt/KeyboardFocusmanager/TypeAhead/MenuItemActivatedTest/MenuItemActivatedTest.java 8302787 windows-all -java/awt/KeyboardFocusmanager/ConsumeNextMnemonicKeyTypedTest/ConsumeNextMnemonicKeyTypedTest.java 8321303 linux-all java/awt/Dialog/MakeWindowAlwaysOnTop/MakeWindowAlwaysOnTop.java 8266243 macosx-aarch64 java/awt/Dialog/ChoiceModalDialogTest.java 8161475 macosx-all diff --git a/test/jdk/java/awt/KeyboardFocusmanager/ConsumeNextMnemonicKeyTypedTest/ConsumeNextMnemonicKeyTypedTest.java b/test/jdk/java/awt/KeyboardFocusmanager/ConsumeNextMnemonicKeyTypedTest/ConsumeNextMnemonicKeyTypedTest.java index 5b2dc2844f1..60c05fb05a6 100644 --- a/test/jdk/java/awt/KeyboardFocusmanager/ConsumeNextMnemonicKeyTypedTest/ConsumeNextMnemonicKeyTypedTest.java +++ b/test/jdk/java/awt/KeyboardFocusmanager/ConsumeNextMnemonicKeyTypedTest/ConsumeNextMnemonicKeyTypedTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* @test @key headful - @bug 6346690 + @bug 6346690 8361606 8321303 @summary Tests that key_typed is consumed after mnemonic key_pressed is handled for a menu item. @library /test/lib @build jdk.test.lib.Platform From 8cc54ec6b86fc5b80af02939363eccd8e3e899e7 Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Tue, 30 Sep 2025 14:14:53 +0000 Subject: [PATCH 0007/1639] 8368563: JFR: Improve jfr query help text Reviewed-by: mgronlun --- .../jdk/jfr/internal/query/QueryPrinter.java | 2 ++ .../classes/jdk/jfr/internal/tool/Query.java | 31 +++++++++---------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/query/QueryPrinter.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/query/QueryPrinter.java index 0d0310dae5b..9d0ce279abd 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/query/QueryPrinter.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/query/QueryPrinter.java @@ -280,12 +280,14 @@ public final class QueryPrinter { MEDIAN: The numeric median MIN: The numeric minimum P90, P95, P99, P999: The numeric percentile, 90%, 95%, 99% or 99.9% + SET: All unique values in a comma-separated list STDEV: The numeric standard deviation SUM: The numeric sum UNIQUE: The unique number of occurrences of a value Null values are included, but ignored for numeric functions. If no aggregator function is specified, the first non-null value is used. - property, any of the following: + none No formatting for the column cell-height: Maximum height of a table cell missing:whitespace Replace missing values (N/A) with blank space normalized Normalize values between 0 and 1.0 for the column diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Query.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Query.java index d350b4215bf..ec0407a6f04 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Query.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/tool/Query.java @@ -73,27 +73,26 @@ final class Query extends Command { p.println(); p.println(" $ jfr query --verbose \"SELECT * FROM ObjectAllocationSample\" recording.jfr"); p.println(); - p.println(" $ jfr query --width 160 \"SELECT pid, path FROM SystemProcess\" recording.jfr"); + p.println(" $ jfr query --width 160 \"SELECT pid, commandLine FROM SystemProcess\" recording.jfr"); p.println(); p.println(" $ jfr query \"SELECT stackTrace.topFrame AS T, SUM(weight)"); p.println(" FROM ObjectAllocationSample GROUP BY T\" recording.jfr"); p.println(); - p.println("$ jfr JFR.query \"COLUMN 'Method', 'Percentage'"); - p.println(" FORMAT default, normalized;width:10"); - p.println(" SELECT stackTrace.topFrame AS T, COUNT(*) AS C"); - p.println(" GROUP BY T"); - p.println(" FROM ExecutionSample ORDER BY C DESC\" recording.jfr"); + p.println(" $ jfr query \"COLUMN 'Method', 'Percentage'"); + p.println(" FORMAT none, normalized"); + p.println(" SELECT stackTrace.topFrame AS T, COUNT(*) AS C"); + p.println(" FROM ExecutionSample GROUP BY T ORDER BY C DESC\" recording.jfr"); p.println(); - p.println("$ jcmd JFR.query \"COLUMN 'Start', 'GC ID', 'Heap Before GC',"); - p.println(" 'Heap After GC', 'Longest Pause'"); - p.println(" SELECT G.startTime, G.gcId, B.heapUsed,"); - p.println(" A.heapUsed, longestPause"); - p.println(" FROM GarbageCollection AS G,"); - p.println(" GCHeapSummary AS B,"); - p.println(" GCHeapSummary AS A"); - p.println(" WHERE B.when = 'Before GC' AND A.when = 'After GC'"); - p.println(" GROUP BY gcId"); - p.println(" ORDER BY G.startTime\" recording.jfr"); + p.println(" $ jfr query \"COLUMN 'Start', 'GC ID', 'Heap Before GC',"); + p.println(" 'Heap After GC', 'Longest Pause'"); + p.println(" SELECT G.startTime, G.gcId, B.heapUsed,"); + p.println(" A.heapUsed, longestPause"); + p.println(" FROM GarbageCollection AS G,"); + p.println(" GCHeapSummary AS B,"); + p.println(" GCHeapSummary AS A"); + p.println(" WHERE B.when = 'Before GC' AND A.when = 'After GC'"); + p.println(" GROUP BY gcId"); + p.println(" ORDER BY gcId\" recording.jfr"); p.println(); p.println("************************************ WARNING ******************************************"); p.println("The query command is only available in debug builds and is targeted towards OpenJDK"); From 6b4b10200ed10365e1ae1ca02ade773ce5a108c3 Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Tue, 30 Sep 2025 14:24:05 +0000 Subject: [PATCH 0008/1639] 8368809: JFR: Remove events from testSettingConfiguration in TestActiveSettingEvent Reviewed-by: mgronlun --- .../event/runtime/TestActiveSettingEvent.java | 28 ++++--------------- 1 file changed, 5 insertions(+), 23 deletions(-) diff --git a/test/jdk/jdk/jfr/event/runtime/TestActiveSettingEvent.java b/test/jdk/jdk/jfr/event/runtime/TestActiveSettingEvent.java index 92298eaece0..96e251aa077 100644 --- a/test/jdk/jdk/jfr/event/runtime/TestActiveSettingEvent.java +++ b/test/jdk/jdk/jfr/event/runtime/TestActiveSettingEvent.java @@ -245,28 +245,6 @@ public final class TestActiveSettingEvent { System.out.println("Testing configuration " + configurationName); Configuration c = Configuration.getConfiguration(configurationName); Map settingValues = c.getSettings(); - // Don't want to add these settings to the jfc-files we ship since they - // are not useful to configure. They are however needed to make the test - // pass. - settingValues.put(EventNames.ActiveSetting + "#stackTrace", "false"); - settingValues.put(EventNames.ActiveSetting + "#threshold", "0 ns"); - settingValues.put(EventNames.ActiveRecording + "#stackTrace", "false"); - settingValues.put(EventNames.ActiveRecording + "#threshold", "0 ns"); - settingValues.put(EventNames.InitialSecurityProperty + "#threshold", "0 ns"); - settingValues.put(EventNames.JavaExceptionThrow + "#threshold", "0 ns"); - settingValues.put(EventNames.JavaErrorThrow + "#threshold", "0 ns"); - settingValues.put(EventNames.SecurityProperty + "#threshold", "0 ns"); - settingValues.put(EventNames.TLSHandshake + "#threshold", "0 ns"); - settingValues.put(EventNames.X509Certificate + "#threshold", "0 ns"); - settingValues.put(EventNames.X509Validation + "#threshold", "0 ns"); - settingValues.put(EventNames.ProcessStart + "#threshold", "0 ns"); - settingValues.put(EventNames.Deserialization + "#threshold", "0 ns"); - settingValues.put(EventNames.VirtualThreadStart + "#threshold", "0 ns"); - settingValues.put(EventNames.VirtualThreadEnd + "#stackTrace", "false"); - settingValues.put(EventNames.VirtualThreadEnd + "#threshold", "0 ns"); - settingValues.put(EventNames.VirtualThreadSubmitFailed + "#threshold", "0 ns"); - settingValues.put(EventNames.SecurityProviderService + "#threshold", "0 ns"); - try (Recording recording = new Recording(c)) { Map eventTypes = new HashMap<>(); for (EventType et : FlightRecorder.getFlightRecorder().getEventTypes()) { @@ -279,7 +257,11 @@ public final class TestActiveSettingEvent { String settingName = type.getName() + "#" + s.getName(); String value = settingValues.get(settingName); if (value == null) { - throw new Exception("Could not find setting with name " + settingName); + String message = "Could not find setting with name " + settingName + "."; + if (settingName.equals("duration") || settingName.equals("stackTrace")) { + message += " Use @RemoveFields(\"" + settingName + "\") to drop the field."; + } + throw new Exception(message); } // Prefer to have ms unit in jfc file if (value.equals("0 ms")) { From 07ecc93dbd0b74e2362d369e22b5141289eb1f76 Mon Sep 17 00:00:00 2001 From: Robbin Ehn Date: Tue, 30 Sep 2025 15:10:30 +0000 Subject: [PATCH 0009/1639] 8367692: RISC-V: Align post call nop Reviewed-by: fyang, fjiang, mli --- src/hotspot/cpu/riscv/assembler_riscv.hpp | 29 +++++--- .../cpu/riscv/c1_LIRAssembler_riscv.cpp | 6 ++ .../cpu/riscv/macroAssembler_riscv.cpp | 13 ++-- src/hotspot/cpu/riscv/nativeInst_riscv.cpp | 25 ++++--- src/hotspot/cpu/riscv/nativeInst_riscv.hpp | 15 +--- src/hotspot/cpu/riscv/riscv.ad | 26 ++++++- src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp | 69 ++++++++++++------- 7 files changed, 115 insertions(+), 68 deletions(-) diff --git a/src/hotspot/cpu/riscv/assembler_riscv.hpp b/src/hotspot/cpu/riscv/assembler_riscv.hpp index 0828342ee65..0712b60fb2a 100644 --- a/src/hotspot/cpu/riscv/assembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/assembler_riscv.hpp @@ -914,6 +914,17 @@ protected: public: + static uint32_t encode_csrrw(Register Rd, const uint32_t csr, Register Rs1) { + guarantee(is_uimm12(csr), "csr is invalid"); + uint32_t insn = 0; + patch((address)&insn, 6, 0, 0b1110011); + patch((address)&insn, 14, 12, 0b001); + patch_reg((address)&insn, 7, Rd); + patch_reg((address)&insn, 15, Rs1); + patch((address)&insn, 31, 20, csr); + return insn; + } + static uint32_t encode_jal(Register Rd, const int32_t offset) { guarantee(is_simm21(offset) && ((offset % 2) == 0), "offset is invalid."); uint32_t insn = 0; @@ -3693,19 +3704,15 @@ public: // -------------------------- // Upper Immediate Instruction // -------------------------- -#define INSN(NAME) \ - void NAME(Register Rd, int32_t imm) { \ - /* lui -> c.lui */ \ - if (do_compress() && (Rd != x0 && Rd != x2 && imm != 0 && is_simm18(imm))) { \ - c_lui(Rd, imm); \ - return; \ - } \ - _lui(Rd, imm); \ + void lui(Register Rd, int32_t imm) { + /* lui -> c.lui */ + if (do_compress() && (Rd != x0 && Rd != x2 && imm != 0 && is_simm18(imm))) { + c_lui(Rd, imm); + return; + } + _lui(Rd, imm); } - INSN(lui); - -#undef INSN // Cache Management Operations // These instruction may be turned off for user space. diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp index adc79350be6..9d8ae770ccf 100644 --- a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp @@ -1350,6 +1350,7 @@ void LIR_Assembler::align_call(LIR_Code code) { } void LIR_Assembler::call(LIR_OpJavaCall* op, relocInfo::relocType rtype) { + Assembler::IncompressibleScope scope(_masm); address call = __ reloc_call(Address(op->addr(), rtype)); if (call == nullptr) { bailout("reloc call address stub overflow"); @@ -1360,6 +1361,7 @@ void LIR_Assembler::call(LIR_OpJavaCall* op, relocInfo::relocType rtype) { } void LIR_Assembler::ic_call(LIR_OpJavaCall* op) { + Assembler::IncompressibleScope scope(_masm); address call = __ ic_call(op->addr()); if (call == nullptr) { bailout("reloc call address stub overflow"); @@ -1842,6 +1844,10 @@ void LIR_Assembler::leal(LIR_Opr addr, LIR_Opr dest, LIR_PatchCode patch_code, C void LIR_Assembler::rt_call(LIR_Opr result, address dest, const LIR_OprList* args, LIR_Opr tmp, CodeEmitInfo* info) { assert(!tmp->is_valid(), "don't need temporary"); + Assembler::IncompressibleScope scope(_masm); + // Post call nops must be natural aligned due to cmodx rules. + align_call(lir_rtcall); + __ rt_call(dest); if (info != nullptr) { diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp index c9de1db0308..5c85cc13bed 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp @@ -355,14 +355,15 @@ void MacroAssembler::call_VM(Register oop_result, } void MacroAssembler::post_call_nop() { + assert(!in_compressible_scope(), "Must be"); + assert_alignment(pc()); if (!Continuations::enabled()) { return; } - relocate(post_call_nop_Relocation::spec(), [&] { - InlineSkippedInstructionsCounter skipCounter(this); - nop(); - li32(zr, 0); - }); + relocate(post_call_nop_Relocation::spec()); + InlineSkippedInstructionsCounter skipCounter(this); + nop(); + li32(zr, 0); } // these are no-ops overridden by InterpreterMacroAssembler @@ -5013,7 +5014,7 @@ address MacroAssembler::reloc_call(Address entry, Register tmp) { address MacroAssembler::ic_call(address entry, jint method_index) { RelocationHolder rh = virtual_call_Relocation::spec(pc(), method_index); - IncompressibleScope scope(this); // relocations + assert(!in_compressible_scope(), "Must be"); movptr(t0, (address)Universe::non_oop_word(), t1); assert_cond(entry != nullptr); return reloc_call(Address(entry, rh)); diff --git a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp index 72cc95a595d..5d1cac72ade 100644 --- a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp +++ b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp @@ -331,13 +331,10 @@ bool NativeInstruction::is_safepoint_poll() { return MacroAssembler::is_lwu_to_zr(address(this)); } -void NativeIllegalInstruction::insert(address code_pos) { - assert_cond(code_pos != nullptr); - Assembler::sd_instr(code_pos, 0xffffffff); // all bits ones is permanently reserved as an illegal instruction -} - bool NativeInstruction::is_stop() { - return uint_at(0) == 0xc0101073; // an illegal instruction, 'csrrw x0, time, x0' + // an illegal instruction, 'csrrw x0, time, x0' + uint32_t encoded = Assembler::encode_csrrw(x0, Assembler::time, x0); + return uint_at(0) == encoded; } //------------------------------------------------------------------- @@ -347,6 +344,8 @@ void NativeGeneralJump::insert_unconditional(address code_pos, address entry) { MacroAssembler a(&cb); Assembler::IncompressibleScope scope(&a); // Fixed length: see NativeGeneralJump::get_instruction_size() + MacroAssembler::assert_alignment(code_pos); + int32_t offset = 0; a.movptr(t1, entry, offset, t0); // lui, lui, slli, add a.jr(t1, offset); // jalr @@ -378,6 +377,7 @@ bool NativePostCallNop::decode(int32_t& oopmap_slot, int32_t& cb_offset) const { } bool NativePostCallNop::patch(int32_t oopmap_slot, int32_t cb_offset) { + MacroAssembler::assert_alignment(addr_at(4)); if (((oopmap_slot & 0xff) != oopmap_slot) || ((cb_offset & 0xffffff) != cb_offset)) { return false; // cannot encode } @@ -389,14 +389,17 @@ bool NativePostCallNop::patch(int32_t oopmap_slot, int32_t cb_offset) { return true; // successfully encoded } -void NativeDeoptInstruction::verify() { +bool NativeDeoptInstruction::is_deopt_at(address instr) { + assert(instr != nullptr, "Must be"); + uint32_t value = Assembler::ld_instr(instr); + uint32_t encoded = Assembler::encode_csrrw(x0, Assembler::instret, x0); + return value == encoded; } // Inserts an undefined instruction at a given pc void NativeDeoptInstruction::insert(address code_pos) { - // 0xc0201073 encodes CSRRW x0, instret, x0 - uint32_t insn = 0xc0201073; - uint32_t *pos = (uint32_t *) code_pos; - *pos = insn; + MacroAssembler::assert_alignment(code_pos); + uint32_t encoded = Assembler::encode_csrrw(x0, Assembler::instret, x0); + Assembler::sd_instr(code_pos, encoded); ICache::invalidate_range(code_pos, 4); } diff --git a/src/hotspot/cpu/riscv/nativeInst_riscv.hpp b/src/hotspot/cpu/riscv/nativeInst_riscv.hpp index 4235e23d421..d990cfbc50d 100644 --- a/src/hotspot/cpu/riscv/nativeInst_riscv.hpp +++ b/src/hotspot/cpu/riscv/nativeInst_riscv.hpp @@ -294,12 +294,6 @@ inline NativeGeneralJump* nativeGeneralJump_at(address addr) { return jump; } -class NativeIllegalInstruction: public NativeInstruction { - public: - // Insert illegal opcode as specific address - static void insert(address code_pos); -}; - inline bool NativeInstruction::is_nop() const { uint32_t insn = Assembler::ld_instr(addr_at(0)); return insn == 0x13; @@ -353,14 +347,7 @@ class NativeDeoptInstruction: public NativeInstruction { address instruction_address() const { return addr_at(instruction_offset); } address next_instruction_address() const { return addr_at(instruction_size); } - void verify(); - - static bool is_deopt_at(address instr) { - assert(instr != nullptr, ""); - uint32_t value = Assembler::ld_instr(instr); - // 0xc0201073 encodes CSRRW x0, instret, x0 - return value == 0xc0201073; - } + static bool is_deopt_at(address instr); // MT-safe patching static void insert(address code_pos); diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad index 739a525c9a4..d816f2405c4 100644 --- a/src/hotspot/cpu/riscv/riscv.ad +++ b/src/hotspot/cpu/riscv/riscv.ad @@ -1269,6 +1269,26 @@ int CallDynamicJavaDirectNode::compute_padding(int current_offset) const return align_up(current_offset, alignment_required()) - current_offset; } +int CallRuntimeDirectNode::compute_padding(int current_offset) const +{ + return align_up(current_offset, alignment_required()) - current_offset; +} + +int CallLeafDirectNode::compute_padding(int current_offset) const +{ + return align_up(current_offset, alignment_required()) - current_offset; +} + +int CallLeafDirectVectorNode::compute_padding(int current_offset) const +{ + return align_up(current_offset, alignment_required()) - current_offset; +} + +int CallLeafNoFPDirectNode::compute_padding(int current_offset) const +{ + return align_up(current_offset, alignment_required()) - current_offset; +} + //============================================================================= #ifndef PRODUCT @@ -8175,7 +8195,7 @@ instruct unnecessary_membar_volatile_rvtso() %{ ins_cost(0); size(0); - + format %{ "#@unnecessary_membar_volatile_rvtso (unnecessary so empty encoding)" %} ins_encode %{ __ block_comment("unnecessary_membar_volatile_rvtso"); @@ -10509,6 +10529,7 @@ instruct CallRuntimeDirect(method meth) ins_encode(riscv_enc_java_to_runtime(meth)); ins_pipe(pipe_class_call); + ins_alignment(4); %} // Call Runtime Instruction @@ -10526,6 +10547,7 @@ instruct CallLeafDirect(method meth) ins_encode(riscv_enc_java_to_runtime(meth)); ins_pipe(pipe_class_call); + ins_alignment(4); %} // Call Runtime Instruction without safepoint and with vector arguments @@ -10543,6 +10565,7 @@ instruct CallLeafDirectVector(method meth) ins_encode(riscv_enc_java_to_runtime(meth)); ins_pipe(pipe_class_call); + ins_alignment(4); %} // Call Runtime Instruction @@ -10560,6 +10583,7 @@ instruct CallLeafNoFPDirect(method meth) ins_encode(riscv_enc_java_to_runtime(meth)); ins_pipe(pipe_class_call); + ins_alignment(4); %} // ============================================================================ diff --git a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp index 34f0f63dbc8..94506e9f19d 100644 --- a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp +++ b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp @@ -1002,20 +1002,23 @@ static void gen_continuation_enter(MacroAssembler* masm, __ bnez(c_rarg2, call_thaw); - // Make sure the call is patchable - __ align(NativeInstruction::instruction_size); + address call_pc; + { + Assembler::IncompressibleScope scope(masm); + // Make sure the call is patchable + __ align(NativeInstruction::instruction_size); - const address tr_call = __ reloc_call(resolve); - if (tr_call == nullptr) { - fatal("CodeCache is full at gen_continuation_enter"); + call_pc = __ reloc_call(resolve); + if (call_pc == nullptr) { + fatal("CodeCache is full at gen_continuation_enter"); + } + + oop_maps->add_gc_map(__ pc() - start, map); + __ post_call_nop(); } - - oop_maps->add_gc_map(__ pc() - start, map); - __ post_call_nop(); - __ j(exit); - address stub = CompiledDirectCall::emit_to_interp_stub(masm, tr_call); + address stub = CompiledDirectCall::emit_to_interp_stub(masm, call_pc); if (stub == nullptr) { fatal("CodeCache is full at gen_continuation_enter"); } @@ -1034,26 +1037,36 @@ static void gen_continuation_enter(MacroAssembler* masm, __ bnez(c_rarg2, call_thaw); - // Make sure the call is patchable - __ align(NativeInstruction::instruction_size); + address call_pc; + { + Assembler::IncompressibleScope scope(masm); + // Make sure the call is patchable + __ align(NativeInstruction::instruction_size); - const address tr_call = __ reloc_call(resolve); - if (tr_call == nullptr) { - fatal("CodeCache is full at gen_continuation_enter"); + call_pc = __ reloc_call(resolve); + if (call_pc == nullptr) { + fatal("CodeCache is full at gen_continuation_enter"); + } + + oop_maps->add_gc_map(__ pc() - start, map); + __ post_call_nop(); } - oop_maps->add_gc_map(__ pc() - start, map); - __ post_call_nop(); - __ j(exit); __ bind(call_thaw); - ContinuationEntry::_thaw_call_pc_offset = __ pc() - start; - __ rt_call(CAST_FROM_FN_PTR(address, StubRoutines::cont_thaw())); - oop_maps->add_gc_map(__ pc() - start, map->deep_copy()); - ContinuationEntry::_return_pc_offset = __ pc() - start; - __ post_call_nop(); + // Post call nops must be natural aligned due to cmodx rules. + { + Assembler::IncompressibleScope scope(masm); + __ align(NativeInstruction::instruction_size); + + ContinuationEntry::_thaw_call_pc_offset = __ pc() - start; + __ rt_call(CAST_FROM_FN_PTR(address, StubRoutines::cont_thaw())); + oop_maps->add_gc_map(__ pc() - start, map->deep_copy()); + ContinuationEntry::_return_pc_offset = __ pc() - start; + __ post_call_nop(); + } __ bind(exit); ContinuationEntry::_cleanup_offset = __ pc() - start; @@ -1082,7 +1095,7 @@ static void gen_continuation_enter(MacroAssembler* masm, __ jr(x11); // the exception handler } - address stub = CompiledDirectCall::emit_to_interp_stub(masm, tr_call); + address stub = CompiledDirectCall::emit_to_interp_stub(masm, call_pc); if (stub == nullptr) { fatal("CodeCache is full at gen_continuation_enter"); } @@ -1115,10 +1128,16 @@ static void gen_continuation_yield(MacroAssembler* masm, __ mv(c_rarg1, sp); + // Post call nops must be natural aligned due to cmodx rules. + __ align(NativeInstruction::instruction_size); + frame_complete = __ pc() - start; address the_pc = __ pc(); - __ post_call_nop(); // this must be exactly after the pc value that is pushed into the frame info, we use this nop for fast CodeBlob lookup + { + Assembler::IncompressibleScope scope(masm); + __ post_call_nop(); // this must be exactly after the pc value that is pushed into the frame info, we use this nop for fast CodeBlob lookup + } __ mv(c_rarg0, xthread); __ set_last_Java_frame(sp, fp, the_pc, t0); From fe9dbcc496671a256c61ac52df5580569dbafb0a Mon Sep 17 00:00:00 2001 From: Francesco Andreuzzi Date: Tue, 30 Sep 2025 16:15:21 +0000 Subject: [PATCH 0010/1639] 8368599: ShenandoahConcurrentMark could use ThreadsClaimTokenScope Reviewed-by: ayang, shade, wkemper --- .../share/gc/shenandoah/shenandoahConcurrentMark.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp index facba2236be..005d6c42f8c 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentMark.cpp @@ -25,7 +25,6 @@ #include "gc/shared/satbMarkQueue.hpp" -#include "gc/shared/strongRootsScope.hpp" #include "gc/shared/taskTerminator.hpp" #include "gc/shenandoah/shenandoahBarrierSet.inline.hpp" #include "gc/shenandoah/shenandoahClosures.inline.hpp" @@ -94,10 +93,12 @@ private: ShenandoahConcurrentMark* _cm; TaskTerminator* _terminator; bool _dedup_string; + ThreadsClaimTokenScope _threads_claim_token_scope; // needed for Threads::possibly_parallel_threads_do public: ShenandoahFinalMarkingTask(ShenandoahConcurrentMark* cm, TaskTerminator* terminator, bool dedup_string) : - WorkerTask("Shenandoah Final Mark"), _cm(cm), _terminator(terminator), _dedup_string(dedup_string) { + WorkerTask("Shenandoah Final Mark"), _cm(cm), _terminator(terminator), _dedup_string(dedup_string), + _threads_claim_token_scope() { } void work(uint worker_id) { @@ -297,7 +298,6 @@ void ShenandoahConcurrentMark::finish_mark_work() { uint nworkers = heap->workers()->active_workers(); task_queues()->reserve(nworkers); - StrongRootsScope scope(nworkers); TaskTerminator terminator(nworkers, task_queues()); switch (_generation->type()) { From 9b02896b4725ef932a23be11ff76ce04bda0d652 Mon Sep 17 00:00:00 2001 From: Mohamed Issa Date: Tue, 30 Sep 2025 21:08:06 +0000 Subject: [PATCH 0011/1639] 8360558: Use hex literals instead of decimal literals in math intrinsic constants Reviewed-by: mhaessig, sparasa, jbhateja --- .../cpu/x86/stubGenerator_x86_64_cbrt.cpp | 176 ++++----- .../cpu/x86/stubGenerator_x86_64_tanh.cpp | 368 +++++++++--------- 2 files changed, 272 insertions(+), 272 deletions(-) diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_cbrt.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_cbrt.cpp index c35f1b9f65e..73330dedc0f 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64_cbrt.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_cbrt.cpp @@ -49,142 +49,142 @@ /* Represents 0x7FFFFFFFFFFFFFFF double precision in lower 64 bits*/ ATTRIBUTE_ALIGNED(16) static const juint _ABS_MASK[] = { - 4294967295, 2147483647, 0, 0 + 0xFFFFFFFFUL, 0x7FFFFFFFUL, 0x00000000UL, 0x00000000UL }; ATTRIBUTE_ALIGNED(4) static const juint _SIG_MASK[] = { - 0, 1032192 + 0x00000000UL, 0x000FC000UL }; ATTRIBUTE_ALIGNED(4) static const juint _EXP_MASK[] = { - 0, 3220176896 + 0x00000000UL, 0xBFF00000UL }; ATTRIBUTE_ALIGNED(4) static const juint _EXP_MSK2[] = { - 0, 3220193280 + 0x00000000UL, 0xBFF04000UL }; ATTRIBUTE_ALIGNED(4) static const juint _EXP_MSK3[] = { - 4294967295, 1048575 + 0xFFFFFFFFUL, 0x000FFFFFUL }; ATTRIBUTE_ALIGNED(4) static const juint _SCALE63[] = { - 0, 1138753536 + 0x00000000UL, 0x43E00000UL }; ATTRIBUTE_ALIGNED(4) static const juint _ZERON[] = { - 0, 2147483648 + 0x00000000UL, 0x80000000UL }; ATTRIBUTE_ALIGNED(4) static const juint _INF[] = { - 0, 2146435072 + 0x00000000UL, 0x7FF00000UL }; ATTRIBUTE_ALIGNED(4) static const juint _NEG_INF[] = { - 0, 4293918720 + 0x00000000UL, 0xFFF00000UL }; ATTRIBUTE_ALIGNED(16) static const juint _coeff_table[] = { - 1553778919, 3213899486, 3534952507, 3215266280, 1646371399, - 3214412045, 477218588, 3216798151, 3582521621, 1066628362, - 1007461464, 1068473053, 889629714, 1067378449, 1431655765, - 1070945621 + 0x5C9CC8E7UL, 0xBF9036DEUL, 0xD2B3183BUL, 0xBFA511E8UL, 0x6221A247UL, + 0xBF98090DUL, 0x1C71C71CUL, 0xBFBC71C7UL, 0xD588F115UL, 0x3F93750AUL, + 0x3C0CA458UL, 0x3FAF9ADDUL, 0x3506AC12UL, 0x3F9EE711UL, 0x55555555UL, + 0x3FD55555UL }; ATTRIBUTE_ALIGNED(4) static const juint _rcp_table[] = { - 528611360, 3220144632, 2884679527, 3220082993, 1991868891, 3220024928, - 2298714891, 3219970134, 58835168, 3219918343, 3035110223, 3219869313, - 1617585086, 3219822831, 2500867033, 3219778702, 4241943008, 3219736752, - 258732970, 3219696825, 404232216, 3219658776, 2172167368, 3219622476, - 1544257904, 3219587808, 377579543, 3219554664, 1616385542, 3219522945, - 813783277, 3219492562, 3940743189, 3219463431, 2689777499, 3219435478, - 1700977147, 3219408632, 3169102082, 3219382828, 327235604, 3219358008, - 1244336319, 3219334115, 1300311200, 3219311099, 3095471925, 3219288912, - 2166487928, 3219267511, 2913108253, 3219246854, 293672978, 3219226904, - 288737297, 3219207624, 1810275472, 3219188981, 174592167, 3219170945, - 3539053052, 3219153485, 2164392968, 3219136576 + 0x1F81F820UL, 0xBFEF81F8UL, 0xABF0B767UL, 0xBFEE9131UL, 0x76B981DBUL, 0xBFEDAE60UL, + 0x89039B0BUL, 0xBFECD856UL, 0x0381C0E0UL, 0xBFEC0E07UL, 0xB4E81B4FUL, 0xBFEB4E81UL, + 0x606A63BEUL, 0xBFEA98EFUL, 0x951033D9UL, 0xBFE9EC8EUL, 0xFCD6E9E0UL, 0xBFE948B0UL, + 0x0F6BF3AAUL, 0xBFE8ACB9UL, 0x18181818UL, 0xBFE81818UL, 0x8178A4C8UL, 0xBFE78A4CUL, + 0x5C0B8170UL, 0xBFE702E0UL, 0x16816817UL, 0xBFE68168UL, 0x60581606UL, 0xBFE60581UL, + 0x308158EDUL, 0xBFE58ED2UL, 0xEAE2F815UL, 0xBFE51D07UL, 0xA052BF5BUL, 0xBFE4AFD6UL, + 0x6562D9FBUL, 0xBFE446F8UL, 0xBCE4A902UL, 0xBFE3E22CUL, 0x13813814UL, 0xBFE38138UL, + 0x4A2B10BFUL, 0xBFE323E3UL, 0x4D812CA0UL, 0xBFE2C9FBUL, 0xB8812735UL, 0xBFE27350UL, + 0x8121FB78UL, 0xBFE21FB7UL, 0xADA2811DUL, 0xBFE1CF06UL, 0x11811812UL, 0xBFE18118UL, + 0x1135C811UL, 0xBFE135C8UL, 0x6BE69C90UL, 0xBFE0ECF5UL, 0x0A6810A7UL, 0xBFE0A681UL, + 0xD2F1A9FCUL, 0xBFE0624DUL, 0x81020408UL, 0xBFE02040UL }; ATTRIBUTE_ALIGNED(4) static const juint _cbrt_table[] = { - 572345495, 1072698681, 1998204467, 1072709382, 3861501553, 1072719872, - 2268192434, 1072730162, 2981979308, 1072740260, 270859143, 1072750176, - 2958651392, 1072759916, 313113243, 1072769490, 919449400, 1072778903, - 2809328903, 1072788162, 2222981587, 1072797274, 2352530781, 1072806244, - 594152517, 1072815078, 1555767199, 1072823780, 4282421314, 1072832355, - 2355578597, 1072840809, 1162590619, 1072849145, 797864051, 1072857367, - 431273680, 1072865479, 2669831148, 1072873484, 733477752, 1072881387, - 4280220604, 1072889189, 801961634, 1072896896, 2915370760, 1072904508, - 1159613482, 1072912030, 2689944798, 1072919463, 1248687822, 1072926811, - 2967951030, 1072934075, 630170432, 1072941259, 3760898254, 1072948363, - 0, 1072955392, 2370273294, 1072962345, 1261754802, 1072972640, - 546334065, 1072986123, 1054893830, 1072999340, 1571187597, 1073012304, - 1107975175, 1073025027, 3606909377, 1073037519, 1113616747, 1073049792, - 4154744632, 1073061853, 3358931423, 1073073713, 4060702372, 1073085379, - 747576176, 1073096860, 3023138255, 1073108161, 1419988548, 1073119291, - 1914185305, 1073130255, 294389948, 1073141060, 3761802570, 1073151710, - 978281566, 1073162213, 823148820, 1073172572, 2420954441, 1073182792, - 3815449908, 1073192878, 2046058587, 1073202835, 1807524753, 1073212666, - 2628681401, 1073222375, 3225667357, 1073231966, 1555307421, 1073241443, - 3454043099, 1073250808, 1208137896, 1073260066, 3659916772, 1073269218, - 1886261264, 1073278269, 3593647839, 1073287220, 3086012205, 1073296075, - 2769796922, 1073304836, 888716057, 1073317807, 2201465623, 1073334794, - 164369365, 1073351447, 3462666733, 1073367780, 2773905457, 1073383810, - 1342879088, 1073399550, 2543933975, 1073415012, 1684477781, 1073430209, - 3532178543, 1073445151, 1147747300, 1073459850, 1928031793, 1073474314, - 2079717015, 1073488553, 4016765315, 1073502575, 3670431139, 1073516389, - 3549227225, 1073530002, 11637607, 1073543422, 588220169, 1073556654, - 2635407503, 1073569705, 2042029317, 1073582582, 1925128962, 1073595290, - 4136375664, 1073607834, 759964600, 1073620221, 4257606771, 1073632453, - 297278907, 1073644538, 3655053093, 1073656477, 2442253172, 1073668277, - 1111876799, 1073679941, 3330973139, 1073691472, 3438879452, 1073702875, - 3671565478, 1073714153, 1317849547, 1073725310, 1642364115, 1073736348 + 0x221D4C97UL, 0x3FF01539UL, 0x771A2E33UL, 0x3FF03F06UL, 0xE629D671UL, 0x3FF06800UL, + 0x8731DEB2UL, 0x3FF09032UL, 0xB1BD64ACUL, 0x3FF0B7A4UL, 0x1024FB87UL, 0x3FF0DE60UL, + 0xB0597000UL, 0x3FF1046CUL, 0x12A9BA9BUL, 0x3FF129D2UL, 0x36CDAF38UL, 0x3FF14E97UL, + 0xA772F507UL, 0x3FF172C2UL, 0x848001D3UL, 0x3FF1965AUL, 0x8C38C55DUL, 0x3FF1B964UL, + 0x236A0C45UL, 0x3FF1DBE6UL, 0x5CBB1F9FUL, 0x3FF1FDE4UL, 0xFF409042UL, 0x3FF21F63UL, + 0x8C6746E5UL, 0x3FF24069UL, 0x454BB99BUL, 0x3FF260F9UL, 0x2F8E7073UL, 0x3FF28117UL, + 0x19B4B6D0UL, 0x3FF2A0C7UL, 0x9F2263ECUL, 0x3FF2C00CUL, 0x2BB7FB78UL, 0x3FF2DEEBUL, + 0xFF1EFBBCUL, 0x3FF2FD65UL, 0x2FCCF6A2UL, 0x3FF31B80UL, 0xADC50708UL, 0x3FF3393CUL, + 0x451E4C2AUL, 0x3FF3569EUL, 0xA0554CDEUL, 0x3FF373A7UL, 0x4A6D76CEUL, 0x3FF3905BUL, + 0xB0E756B6UL, 0x3FF3ACBBUL, 0x258FA340UL, 0x3FF3C8CBUL, 0xE02AC0CEUL, 0x3FF3E48BUL, + 0x00000000UL, 0x3FF40000UL, 0x8D47800EUL, 0x3FF41B29UL, 0x4B34D9B2UL, 0x3FF44360UL, + 0x20906571UL, 0x3FF4780BUL, 0x3EE06706UL, 0x3FF4ABACUL, 0x5DA66B8DUL, 0x3FF4DE50UL, + 0x420A5C07UL, 0x3FF51003UL, 0xD6FD11C1UL, 0x3FF540CFUL, 0x4260716BUL, 0x3FF570C0UL, + 0xF7A45F38UL, 0x3FF59FDDUL, 0xC83539DFUL, 0x3FF5CE31UL, 0xF20966A4UL, 0x3FF5FBC3UL, + 0x2C8F1B70UL, 0x3FF6289CUL, 0xB4316DCFUL, 0x3FF654C1UL, 0x54A34E44UL, 0x3FF6803BUL, + 0x72182659UL, 0x3FF6AB0FUL, 0x118C08BCUL, 0x3FF6D544UL, 0xE0388D4AUL, 0x3FF6FEDEUL, + 0x3A4F645EUL, 0x3FF727E5UL, 0x31104114UL, 0x3FF7505CUL, 0x904CD549UL, 0x3FF77848UL, + 0xE36B2534UL, 0x3FF79FAEUL, 0x79F4605BUL, 0x3FF7C693UL, 0x6BBCA391UL, 0x3FF7ECFAUL, + 0x9CAE7EB9UL, 0x3FF812E7UL, 0xC043C71DUL, 0x3FF8385EUL, 0x5CB41B9DUL, 0x3FF85D63UL, + 0xCDE083DBUL, 0x3FF881F8UL, 0x4802B8A8UL, 0x3FF8A622UL, 0xDA25E5E4UL, 0x3FF8C9E2UL, + 0x706E1010UL, 0x3FF8ED3DUL, 0xD632B6DFUL, 0x3FF91034UL, 0xB7F0CF2DUL, 0x3FF932CBUL, + 0xA517BF3AUL, 0x3FF95504UL, 0x34F8BB19UL, 0x3FF987AFUL, 0x8337B317UL, 0x3FF9CA0AUL, + 0x09CC13D5UL, 0x3FFA0B17UL, 0xCE6419EDUL, 0x3FFA4AE4UL, 0xA5567031UL, 0x3FFA8982UL, + 0x500AB570UL, 0x3FFAC6FEUL, 0x97A15A17UL, 0x3FFB0364UL, 0x64671755UL, 0x3FFB3EC1UL, + 0xD288C46FUL, 0x3FFB791FUL, 0x44693BE4UL, 0x3FFBB28AUL, 0x72EB6E31UL, 0x3FFBEB0AUL, + 0x7BF5F697UL, 0x3FFC22A9UL, 0xEF6AF983UL, 0x3FFC596FUL, 0xDAC655A3UL, 0x3FFC8F65UL, + 0xD38CE8D9UL, 0x3FFCC492UL, 0x00B19367UL, 0x3FFCF8FEUL, 0x230F8709UL, 0x3FFD2CAEUL, + 0x9D15208FUL, 0x3FFD5FA9UL, 0x79B6E505UL, 0x3FFD91F6UL, 0x72BF2302UL, 0x3FFDC39AUL, + 0xF68C1570UL, 0x3FFDF49AUL, 0x2D4C23B8UL, 0x3FFE24FDUL, 0xFDC5EC73UL, 0x3FFE54C5UL, + 0x11B81DBBUL, 0x3FFE83FAUL, 0xD9DBAF25UL, 0x3FFEB29DUL, 0x9191D374UL, 0x3FFEE0B5UL, + 0x4245E4BFUL, 0x3FFF0E45UL, 0xC68A9DD3UL, 0x3FFF3B50UL, 0xCCF922DCUL, 0x3FFF67DBUL, + 0xDAD7A4A6UL, 0x3FFF93E9UL, 0x4E8CC9CBUL, 0x3FFFBF7EUL, 0x61E47CD3UL, 0x3FFFEA9CUL }; ATTRIBUTE_ALIGNED(4) static const juint _D_table[] = { - 4050900474, 1014427190, 1157977860, 1016444461, 1374568199, 1017271387, - 2809163288, 1016882676, 3742377377, 1013168191, 3101606597, 1017541672, - 65224358, 1017217597, 2691591250, 1017266643, 4020758549, 1017689313, - 1316310992, 1018030788, 1031537856, 1014090882, 3261395239, 1016413641, - 886424999, 1016313335, 3114776834, 1014195875, 1681120620, 1017825416, - 1329600273, 1016625740, 465474623, 1017097119, 4251633980, 1017169077, - 1986990133, 1017710645, 752958613, 1017159641, 2216216792, 1018020163, - 4282860129, 1015924861, 1557627859, 1016039538, 3889219754, 1018086237, - 3684996408, 1017353275, 723532103, 1017717141, 2951149676, 1012528470, - 831890937, 1017830553, 1031212645, 1017387331, 2741737450, 1017604974, - 2863311531, 1003776682, 4276736099, 1013153088, 4111778382, 1015673686, - 1728065769, 1016413986, 2708718031, 1018078833, 1069335005, 1015291224, - 700037144, 1016482032, 2904566452, 1017226861, 4074156649, 1017622651, - 25019565, 1015245366, 3601952608, 1015771755, 3267129373, 1017904664, - 503203103, 1014921629, 2122011730, 1018027866, 3927295461, 1014189456, - 2790625147, 1016024251, 1330460186, 1016940346, 4033568463, 1015538390, - 3695818227, 1017509621, 257573361, 1017208868, 3227697852, 1017337964, - 234118548, 1017169577, 4009025803, 1017278524, 1948343394, 1017749310, - 678398162, 1018144239, 3083864863, 1016669086, 2415453452, 1017890370, - 175467344, 1017330033, 3197359580, 1010339928, 2071276951, 1015941358, - 268372543, 1016737773, 938132959, 1017389108, 1816750559, 1017337448, - 4119203749, 1017152174, 2578653878, 1013108497, 2470331096, 1014678606, - 123855735, 1016553320, 1265650889, 1014782687, 3414398172, 1017182638, - 1040773369, 1016158401, 3483628886, 1016886550, 4140499405, 1016191425, - 3893477850, 1016964495, 3935319771, 1009634717, 2978982660, 1015027112, - 2452709923, 1017990229, 3190365712, 1015835149, 4237588139, 1015832925, - 2610678389, 1017962711, 2127316774, 1017405770, 824267502, 1017959463, - 2165924042, 1017912225, 2774007076, 1013257418, 4123916326, 1017582284, - 1976417958, 1016959909, 4092806412, 1017711279, 119251817, 1015363631, - 3475418768, 1017675415, 1972580503, 1015470684, 815541017, 1017517969, - 2429917451, 1017397776, 4062888482, 1016749897, 68284153, 1017925678, - 2207779246, 1016320298, 1183466520, 1017408657, 143326427, 1017060403 + 0xF173D5FAUL, 0x3C76EE36UL, 0x45055704UL, 0x3C95B62DUL, 0x51EE3F07UL, 0x3CA2545BUL, + 0xA7706E18UL, 0x3C9C65F4UL, 0xDF1025A1UL, 0x3C63B83FUL, 0xB8DEC2C5UL, 0x3CA67428UL, + 0x03E33EA6UL, 0x3CA1823DUL, 0xA06E6C52UL, 0x3CA241D3UL, 0xEFA7E815UL, 0x3CA8B4E1UL, + 0x4E754FD0UL, 0x3CADEAC4UL, 0x3D7C04C0UL, 0x3C71CC82UL, 0xC264F127UL, 0x3C953DC9UL, + 0x34D5C5A7UL, 0x3C93B5F7UL, 0xB9A7B902UL, 0x3C7366A3UL, 0x6433DD6CUL, 0x3CAAC888UL, + 0x4F401711UL, 0x3C987A4CUL, 0x1BBE943FUL, 0x3C9FAB9FUL, 0xFD6AC93CUL, 0x3CA0C4B5UL, + 0x766F1035UL, 0x3CA90835UL, 0x2CE13C95UL, 0x3CA09FD9UL, 0x8418C8D8UL, 0x3CADC143UL, + 0xFF474261UL, 0x3C8DC87DUL, 0x5CD783D3UL, 0x3C8F8872UL, 0xE7D0C8AAUL, 0x3CAEC35DUL, + 0xDBA49538UL, 0x3CA3943BUL, 0x2B203947UL, 0x3CA92195UL, 0xAFE6F86CUL, 0x3C59F556UL, + 0x3195A5F9UL, 0x3CAADC99UL, 0x3D770E65UL, 0x3CA41943UL, 0xA36B97EAUL, 0x3CA76B6EUL, + 0xAAAAAAABUL, 0x3BD46AAAUL, 0xFEE9D063UL, 0x3C637D40UL, 0xF514C24EUL, 0x3C89F356UL, + 0x670030E9UL, 0x3C953F22UL, 0xA173C1CFUL, 0x3CAEA671UL, 0x3FBCC1DDUL, 0x3C841D58UL, + 0x29B9B818UL, 0x3C9648F0UL, 0xAD202AB4UL, 0x3CA1A66DUL, 0xF2D6B269UL, 0x3CA7B07BUL, + 0x017DC4ADUL, 0x3C836A36UL, 0xD6B16F60UL, 0x3C8B726BUL, 0xC2BC701DUL, 0x3CABFE18UL, + 0x1DFE451FUL, 0x3C7E799DUL, 0x7E7B5452UL, 0x3CADDF5AUL, 0xEA15C5E5UL, 0x3C734D90UL, + 0xA6558F7BUL, 0x3C8F4CBBUL, 0x4F4D361AUL, 0x3C9D473AUL, 0xF06B5ECFUL, 0x3C87E2D6UL, + 0xDC49B5F3UL, 0x3CA5F6F5UL, 0x0F5A41F1UL, 0x3CA16024UL, 0xC062C2BCUL, 0x3CA3586CUL, + 0x0DF45D94UL, 0x3CA0C6A9UL, 0xEEF4E10BUL, 0x3CA2703CUL, 0x74215C62UL, 0x3CA99F3EUL, + 0x286F88D2UL, 0x3CAFA5EFUL, 0xB7D00B1FUL, 0x3C99239EUL, 0x8FF8E50CUL, 0x3CABC642UL, + 0x0A756B50UL, 0x3CA33971UL, 0xBE93D5DCUL, 0x3C389058UL, 0x7B752D97UL, 0x3C8E08EEUL, + 0x0FFF0A3FUL, 0x3C9A2FEDUL, 0x37EAC5DFUL, 0x3CA42034UL, 0x6C4969DFUL, 0x3CA35668UL, + 0xF5860FA5UL, 0x3CA082AEUL, 0x99B322B6UL, 0x3C62CF11UL, 0x933E42D8UL, 0x3C7AC44EUL, + 0x0761E377UL, 0x3C975F68UL, 0x4B704CC9UL, 0x3C7C5ADFUL, 0xCB8394DCUL, 0x3CA0F9AEUL, + 0x3E08F0F9UL, 0x3C9158C1UL, 0xCFA3F556UL, 0x3C9C7516UL, 0xF6CB01CDUL, 0x3C91D9C1UL, + 0xE811C1DAUL, 0x3C9DA58FUL, 0xEA9036DBUL, 0x3C2DCD9DUL, 0xB18FAB04UL, 0x3C8015A8UL, + 0x92316223UL, 0x3CAD4C55UL, 0xBE291E10UL, 0x3C8C6A0DUL, 0xFC9476ABUL, 0x3C8C615DUL, + 0x9B9BCA75UL, 0x3CACE0D7UL, 0x7ECC4726UL, 0x3CA4614AUL, 0x312152EEUL, 0x3CACD427UL, + 0x811960CAUL, 0x3CAC1BA1UL, 0xA557FD24UL, 0x3C6514CAUL, 0xF5CDF826UL, 0x3CA712CCUL, + 0x75CDBEA6UL, 0x3C9D93A5UL, 0xF3F3450CUL, 0x3CA90AAFUL, 0x071BA369UL, 0x3C85382FUL, + 0xCF26AE90UL, 0x3CA87E97UL, 0x75933097UL, 0x3C86DA5CUL, 0x309C2B19UL, 0x3CA61791UL, + 0x90D5990BUL, 0x3CA44210UL, 0xF22AC222UL, 0x3C9A5F49UL, 0x0411EEF9UL, 0x3CAC502EUL, + 0x839809AEUL, 0x3C93D12AUL, 0x468A4418UL, 0x3CA46C91UL, 0x088AFCDBUL, 0x3C9F1C33UL }; #define __ _masm-> diff --git a/src/hotspot/cpu/x86/stubGenerator_x86_64_tanh.cpp b/src/hotspot/cpu/x86/stubGenerator_x86_64_tanh.cpp index 372c4898f37..dce4fbfc455 100644 --- a/src/hotspot/cpu/x86/stubGenerator_x86_64_tanh.cpp +++ b/src/hotspot/cpu/x86/stubGenerator_x86_64_tanh.cpp @@ -77,226 +77,226 @@ ATTRIBUTE_ALIGNED(4) static const juint _HALFMASK[] = { - 4160749568, 2147483647 + 0xF8000000UL, 0x7FFFFFFFUL }; ATTRIBUTE_ALIGNED(4) static const juint _ONEMASK[] = { - 0, 1072693248 + 0x00000000UL, 0x3FF00000UL }; ATTRIBUTE_ALIGNED(4) static const juint _TWOMASK[] = { - 0, 1073741824 + 0x00000000UL, 0x40000000UL }; ATTRIBUTE_ALIGNED(16) static const juint _MASK3[] = { - 0, 4294967280, 0, 4294967280 + 0x00000000UL, 0xFFFFFFF0UL, 0x00000000UL, 0xFFFFFFF0UL }; ATTRIBUTE_ALIGNED(16) static const juint _RMASK[] = { - 4294705152, 4294967295, 4294705152, 4294967295 + 0xFFFC0000UL, 0xFFFFFFFFUL, 0xFFFC0000UL, 0xFFFFFFFFUL }; ATTRIBUTE_ALIGNED(16) static const juint _L2E[] = { - 1610612736, 1082594631, 4166901572, 1055174155 + 0x60000000UL, 0x40871547UL, 0xF85DDF44UL, 0x3EE4AE0BUL }; ATTRIBUTE_ALIGNED(16) static const juint _Shifter[] = { - 0, 1127743488, 0, 3275227136 + 0x00000000UL, 0x43380000UL, 0x00000000UL, 0xC3380000UL }; ATTRIBUTE_ALIGNED(16) static const juint _cv[] = { - 3884607281, 3168131199, 3607404735, 3190582024, 1874480759, - 1032041131, 4286760334, 1053736893, 4277811695, 3211144770, - 0, 0 + 0xE78A6731UL, 0xBCD5D87FUL, 0xD704A0BFUL, 0xBE2C6B08UL, 0x6FBA4E77UL, + 0x3D83B2ABUL, 0xFF82C58EUL, 0x3ECEBFBDUL, 0xFEFA39EFUL, 0xBF662E42UL, + 0x00000000UL, 0x00000000UL }; ATTRIBUTE_ALIGNED(4) static const juint _pv[] = { - 236289503, 1064135997, 463583772, 3215696314, 1441186365, - 3212977891, 286331153, 1069617425, 2284589306, 1066820852, - 1431655765, 3218429269 + 0x0E157DDFUL, 0x3F6D6D3DUL, 0x1BA1BA1CUL, 0xBFABA1BAUL, 0x55E6C23DUL, + 0xBF8226E3UL, 0x11111111UL, 0x3FC11111UL, 0x882C10FAUL, 0x3F9664F4UL, + 0x55555555UL, 0xBFD55555UL }; ATTRIBUTE_ALIGNED(16) static const juint _T2_neg_f[] = { - 0, 1072693248, 0, 0, 1797923801, 1072687577, - 1950547427, 1013229059, 730821105, 1072681922, 2523232743, 1012067188, - 915592468, 1072676282, 352947894, 3161024371, 2174652632, 1072670657, - 4087714590, 1014450259, 35929225, 1072665048, 2809788041, 3159436968, - 2912730644, 1072659453, 3490067722, 3163405074, 2038973688, 1072653874, - 892941374, 1016046459, 1533953344, 1072648310, 769171851, 1015665633, - 1222472308, 1072642761, 1054357470, 3161021018, 929806999, 1072637227, - 3205336643, 1015259557, 481706282, 1072631708, 1696079173, 3162710528, - 3999357479, 1072626203, 2258941616, 1015924724, 2719515920, 1072620714, - 2760332941, 1015137933, 764307441, 1072615240, 3021057420, 3163329523, - 2256325230, 1072609780, 580117746, 1015317295, 2728693978, 1072604335, - 396109971, 3163462691, 2009970496, 1072598905, 2159039665, 3162572948, - 4224142467, 1072593489, 3389820386, 1015207202, 610758006, 1072588089, - 1965209397, 3161866232, 3884662774, 1072582702, 2158611599, 1014210185, - 991358482, 1072577331, 838715019, 3163157668, 351641897, 1072571974, - 2172261526, 3163010599, 1796832535, 1072566631, 3176955716, 3160585513, - 863738719, 1072561303, 1326992220, 3162613197, 1679558232, 1072555989, - 2390342287, 3163333970, 4076975200, 1072550689, 2029000899, 1015208535, - 3594158869, 1072545404, 2456521700, 3163256561, 64696965, 1072540134, - 1768797490, 1015816960, 1912561781, 1072534877, 3147495102, 1015678253, - 382305176, 1072529635, 2347622376, 3162578625, 3898795731, 1072524406, - 1249994144, 1011869818, 3707479175, 1072519192, 3613079303, 1014164738, - 3939148246, 1072513992, 3210352148, 1015274323, 135105010, 1072508807, - 1906148728, 3163375739, 721996136, 1072503635, 563754734, 1015371318, - 1242007932, 1072498477, 1132034716, 3163339831, 1532734324, 1072493333, - 3094216535, 3163162857, 1432208378, 1072488203, 1401068914, 3162363963, - 778901109, 1072483087, 2248183955, 3161268751, 3706687593, 1072477984, - 3521726940, 1013253067, 1464976603, 1072472896, 3507292405, 3161977534, - 2483480501, 1072467821, 1216371780, 1013034172, 2307442995, 1072462760, - 3190117721, 3162404539, 777507147, 1072457713, 4282924205, 1015187533, - 2029714210, 1072452679, 613660079, 1015099143, 1610600570, 1072447659, - 3766732298, 1015760183, 3657065772, 1072442652, 399025623, 3162957078, - 3716502172, 1072437659, 2303740125, 1014042725, 1631695677, 1072432680, - 2717633076, 3162344026, 1540824585, 1072427714, 1064017011, 3163487690, - 3287523847, 1072422761, 1625971539, 3157009955, 2420883922, 1072417822, - 2049810052, 1014119888, 3080351519, 1072412896, 3379126788, 3157218001, - 815859274, 1072407984, 240396590, 3163487443, 4062661092, 1072403084, - 1422616006, 3163255318, 4076559943, 1072398198, 2119478331, 3160758351, - 703710506, 1072393326, 1384660846, 1015195891, 2380618042, 1072388466, - 3149557219, 3163320799, 364333489, 1072383620, 3923737744, 3161421373, - 3092190715, 1072378786, 814012168, 3159523422, 1822067026, 1072373966, - 1241994956, 1015340290, 697153126, 1072369159, 1283515429, 3163283189, - 3861050111, 1072364364, 254893773, 3162813180, 2572866477, 1072359583, - 878562433, 1015521741, 977020788, 1072354815, 3065100517, 1015541563, - 3218338682, 1072350059, 3404164304, 3162477108, 557149882, 1072345317, - 3672720709, 1014537265, 1434058175, 1072340587, 251133233, 1015085769, - 1405169241, 1072335870, 2998539689, 3162830951, 321958744, 1072331166, - 3401933767, 1015794558, 2331271250, 1072326474, 812057446, 1012207446, - 2990417245, 1072321795, 3683467745, 3163369326, 2152073944, 1072317129, - 1486860576, 3163203456, 3964284211, 1072312475, 2111583915, 1015427164, - 3985553595, 1072307834, 4002146062, 1015834136, 2069751141, 1072303206, - 1562170675, 3162724681, 2366108318, 1072298590, 2867985102, 3161762254, - 434316067, 1072293987, 2028358766, 1013458122, 424392917, 1072289396, - 2749202995, 3162838718, 2191782032, 1072284817, 2960257726, 1013742662, - 1297350157, 1072280251, 1308022040, 3163412558, 1892288442, 1072275697, - 2446255666, 3162600381, 3833209506, 1072271155, 2722920684, 1013754842, - 2682146384, 1072266626, 2082178513, 3163363419, 2591453363, 1072262109, - 2132396182, 3159074198, 3418903055, 1072257604, 2527457337, 3160820604, - 727685349, 1072253112, 2038246809, 3162358742, 2966275557, 1072248631, - 2176155324, 3159842759, 1403662306, 1072244163, 2788809599, 3161671007, - 194117574, 1072239707, 777528612, 3163412089, 3492293770, 1072235262, - 2248032210, 1015386826, 2568320822, 1072230830, 2732824428, 1014352915, - 1577608921, 1072226410, 1875489510, 3162968394, 380978316, 1072222002, - 854188970, 3160462686, 3134592888, 1072217605, 4232266862, 1015991134, - 1110089947, 1072213221, 1451641639, 1015474673, 2759350287, 1072208848, - 1148526634, 1015894933, 3649726105, 1072204487, 4085036346, 1015649474, - 3643909174, 1072200138, 3537586109, 1014354647, 2604962541, 1072195801, - 2614425274, 3163539192, 396319521, 1072191476, 4172420816, 3159074632, - 1176749997, 1072187162, 2738998779, 3162035844, 515457527, 1072182860, - 836709333, 1015651226, 2571947539, 1072178569, 3558159064, 3163376669, - 2916157145, 1072174290, 219487565, 1015309367, 1413356050, 1072170023, - 1651349291, 3162668166, 2224145553, 1072165767, 3482522030, 3161489169, - 919555682, 1072161523, 3121969534, 1012948226, 1660913392, 1072157290, - 4218599604, 1015135707, 19972402, 1072153069, 3507899862, 1016009292, - 158781403, 1072148859, 2221464712, 3163286453, 1944781191, 1072144660, - 3993278767, 3161724279, 950803702, 1072140473, 1655364926, 1015237032, - 1339972927, 1072136297, 167908909, 1015572152, 2980802057, 1072132132, - 378619896, 1015773303, 1447192521, 1072127979, 1462857171, 3162514521, - 903334909, 1072123837, 1636462108, 1015039997, 1218806132, 1072119706, - 1818613052, 3162548441, 2263535754, 1072115586, 752233586, 3162639008, - 3907805044, 1072111477, 2257091225, 3161550407, 1727278727, 1072107380, - 3562710623, 1011471940, 4182873220, 1072103293, 629542646, 3161996303, - 2555984613, 1072099218, 2652555442, 3162552692, 1013258799, 1072095154, - 1748797611, 3160129082, 3721688645, 1072091100, 3069276937, 1015839401, - 1963711167, 1072087058, 1744767757, 3160574294, 4201977662, 1072083026, - 748330254, 1013594357, 1719614413, 1072079006, 330458198, 3163282740, - 2979960120, 1072074996, 2599109725, 1014498493, 3561793907, 1072070997, - 1157054053, 1011890350, 3339203574, 1072067009, 1483497780, 3162408754, - 2186617381, 1072063032, 2270764084, 3163272713, 4273770423, 1072059065, - 3383180809, 3163218901, 885834528, 1072055110, 1973258547, 3162261564, - 488188413, 1072051165, 3199821029, 1015564048, 2956612997, 1072047230, - 2118169751, 3162735553, 3872257780, 1072043306, 1253592103, 1015958334, - 3111574537, 1072039393, 2606161479, 3162759746, 551349105, 1072035491, - 3821916050, 3162106589, 363667784, 1072031599, 813753950, 1015785209, - 2425981843, 1072027717, 2830390851, 3163346599, 2321106615, 1072023846, - 2171176610, 1009535771, 4222122499, 1072019985, 1277378074, 3163256737, - 3712504873, 1072016135, 88491949, 1015427660, 671025100, 1072012296, - 3832014351, 3163022030, 3566716925, 1072008466, 1536826856, 1014142433, - 3689071823, 1072004647, 2321004996, 3162552716, 917841882, 1072000839, - 18715565, 1015659308, 3723038930, 1071997040, 378465264, 3162569582, - 3395129871, 1071993252, 4025345435, 3162335388, 4109806887, 1071989474, - 422403966, 1014469229, 1453150082, 1071985707, 498154669, 3161488062, - 3896463087, 1071981949, 1139797873, 3161233805, 2731501122, 1071978202, - 1774031855, 3162470021, 2135241198, 1071974465, 1236747871, 1013589147, - 1990012071, 1071970738, 3529070563, 3162813193, 2178460671, 1071967021, - 777878098, 3162842493, 2583551245, 1071963314, 3161094195, 1015606491, - 3088564500, 1071959617, 1762311517, 1015045673, 3577096743, 1071955930, - 2951496418, 1013793687, 3933059031, 1071952253, 2133366768, 3161531832, - 4040676318, 1071948586, 4090609238, 1015663458, 3784486610, 1071944929, - 1581883040, 3161698953, 3049340112, 1071941282, 3062915824, 1013170595, - 1720398391, 1071937645, 3980678963, 3163300080, 3978100823, 1071934017, - 3513027190, 1015845963, 1118294578, 1071930400, 2197495694, 3159909401, - 1617004845, 1071926792, 82804944, 1010342778, 1065662932, 1071923194, - 2533670915, 1014530238, 3645941911, 1071919605, 3814685081, 3161573341, - 654919306, 1071916027, 3232961757, 3163047469, 569847338, 1071912458, - 472945272, 3159290729, 3278348324, 1071908898, 3069497416, 1014750712, - 78413852, 1071905349, 4183226867, 3163017251, 3743175029, 1071901808, - 2072812490, 3162175075, 1276261410, 1071898278, 300981948, 1014684169, - 1156440435, 1071894757, 2351451249, 1013967056, 3272845541, 1071891245, - 928852419, 3163488248, 3219942644, 1071887743, 3798990616, 1015368806, - 887463927, 1071884251, 3596744163, 3160794166, 460407023, 1071880768, - 4237175092, 3163138469, 1829099622, 1071877294, 1016661181, 3163461005, - 589198666, 1071873830, 2664346172, 3163157962, 926591435, 1071870375, - 3208833762, 3162913514, 2732492859, 1071866929, 2691479646, 3162255684, - 1603444721, 1071863493, 1548633640, 3162201326, 1726216749, 1071860066, - 2466808228, 3161676405, 2992903935, 1071856648, 2218154406, 1015228193, - 1000925746, 1071853240, 1018491672, 3163309544, 4232894513, 1071849840, - 2383938684, 1014668519, 3991843581, 1071846450, 4092853457, 1014585763, - 171030293, 1071843070, 3526460132, 1014428778, 1253935211, 1071839698, - 1395382931, 3159702613, 2839424854, 1071836335, 1171596163, 1013041679, - 526652809, 1071832982, 4223459736, 1015879375, 2799960843, 1071829637, - 1423655381, 1015022151, 964107055, 1071826302, 2800439588, 3162833221, - 3504003472, 1071822975, 3594001060, 3157330652, 1724976915, 1071819658, - 420909223, 3163117379, 4112506593, 1071816349, 2947355221, 1014371048, - 1972484976, 1071813050, 675290301, 3161640050, 3790955393, 1071809759, - 2352942462, 3163180090, 874372905, 1071806478, 100263788, 1015940732, - 1709341917, 1071803205, 2571168217, 1014152499, 1897844341, 1071799941, - 1254300460, 1015275938, 1337108031, 1071796686, 3203724452, 1014677845, - 4219606026, 1071793439, 2434574742, 1014681548, 1853186616, 1071790202, - 3066496371, 1015656574, 2725843665, 1071786973, 1433917087, 1014838523, - 2440944790, 1071783753, 2492769774, 1014147454, 897099801, 1071780542, - 754756297, 1015241005, 2288159958, 1071777339, 2169144469, 1014876021, - 2218315341, 1071774145, 2694295388, 3163288868, 586995997, 1071770960, - 41662348, 3162627992, 1588871207, 1071767783, 143439582, 3162963416, - 828946858, 1071764615, 10642492, 1015939438, 2502433899, 1071761455, - 2148595913, 1015023991, 2214878420, 1071758304, 892270087, 3163116422, - 4162030108, 1071755161, 2763428480, 1015529349, 3949972341, 1071752027, - 2068408548, 1014913868, 1480023343, 1071748902, 2247196168, 1015327453, - 948735466, 1071745785, 3516338028, 3162574883, 2257959872, 1071742676, - 3802946148, 1012964927, 1014845819, 1071739576, 3117910646, 3161559105, - 1416741826, 1071736484, 2196380210, 1011413563, 3366293073, 1071733400, - 3119426314, 1014120554, 2471440686, 1071730325, 968836267, 3162214888, - 2930322912, 1071727258, 2599499422, 3162714047, 351405227, 1071724200, - 3125337328, 3159822479, 3228316108, 1071721149, 3010241991, 3158422804, - 2875075254, 1071718107, 4144233330, 3163333716, 3490863953, 1071715073, - 960797498, 3162948880, 685187902, 1071712048, 378731989, 1014843115, - 2952712987, 1071709030, 3293494651, 3160120301, 1608493509, 1071706021, - 3159622171, 3162807737, 852742562, 1071703020, 667253586, 1009793559, - 590962156, 1071700027, 3829346666, 3163275597, 728909815, 1071697042, - 383930225, 1015029468, 1172597893, 1071694065, 114433263, 1015347593, - 1828292879, 1071691096, 1255956747, 1015588398, 2602514713, 1071688135, - 2268929336, 1014354284, 3402036099, 1071685182, 405889334, 1015105656, - 4133881824, 1071682237, 2148155345, 3162931299, 410360776, 1071679301, - 1269990655, 1011975870, 728934454, 1071676372, 1413842688, 1014178612, - 702412510, 1071673451, 3803266087, 3162280415, 238821257, 1071670538, - 1469694871, 3162884987, 3541402996, 1071667632, 2759177317, 1014854626, - 1928746161, 1071664735, 983617676, 1014285177, 3899555717, 1071661845, - 427280750, 3162546972, 772914124, 1071658964, 4004372762, 1012230161, - 1048019041, 1071656090, 1398474845, 3160510595, 339411585, 1071653224, - 264588982, 3161636657, 2851812149, 1071650365, 2595802551, 1015767337, - 4200250559, 1071647514, 2808127345, 3161781938 + 0x00000000UL, 0x3FF00000UL, 0x00000000UL, 0x00000000UL, 0x6B2A23D9UL, 0x3FEFE9D9UL, + 0x7442FDE3UL, 0x3C64A603UL, 0x2B8F71F1UL, 0x3FEFD3C2UL, 0x966579E7UL, 0x3C52EB74UL, + 0x3692D514UL, 0x3FEFBDBAUL, 0x15098EB6UL, 0xBC696773UL, 0x819E90D8UL, 0x3FEFA7C1UL, + 0xF3A5931EUL, 0x3C774853UL, 0x02243C89UL, 0x3FEF91D8UL, 0xA779F689UL, 0xBC512EA8UL, + 0xAD9CBE14UL, 0x3FEF7BFDUL, 0xD006350AUL, 0xBC8DBB12UL, 0x798844F8UL, 0x3FEF6632UL, + 0x3539343EUL, 0x3C8FA37BUL, 0x5B6E4540UL, 0x3FEF5076UL, 0x2DD8A18BUL, 0x3C89D3E1UL, + 0x48DD7274UL, 0x3FEF3AC9UL, 0x3ED837DEUL, 0xBC695A5AUL, 0x376BBA97UL, 0x3FEF252BUL, + 0xBF0D8E43UL, 0x3C83A1A5UL, 0x1CB6412AUL, 0x3FEF0F9CUL, 0x65181D45UL, 0xBC832200UL, + 0xEE615A27UL, 0x3FEEFA1BUL, 0x86A4B6B0UL, 0x3C8DC7F4UL, 0xA2188510UL, 0x3FEEE4AAUL, + 0xA487568DUL, 0x3C81C68DUL, 0x2D8E67F1UL, 0x3FEECF48UL, 0xB411AD8CUL, 0xBC8C93F3UL, + 0x867CCA6EUL, 0x3FEEB9F4UL, 0x2293E4F2UL, 0x3C84832FUL, 0xA2A490DAUL, 0x3FEEA4AFUL, + 0x179C2893UL, 0xBC8E9C23UL, 0x77CDB740UL, 0x3FEE8F79UL, 0x80B054B1UL, 0xBC810894UL, + 0xFBC74C83UL, 0x3FEE7A51UL, 0xCA0C8DE2UL, 0x3C82D522UL, 0x24676D76UL, 0x3FEE6539UL, + 0x7522B735UL, 0xBC763FF8UL, 0xE78B3FF6UL, 0x3FEE502EUL, 0x80A9CC8FUL, 0x3C739E89UL, + 0x3B16EE12UL, 0x3FEE3B33UL, 0x31FDC68BUL, 0xBC89F4A4UL, 0x14F5A129UL, 0x3FEE2646UL, + 0x817A1496UL, 0xBC87B627UL, 0x6B197D17UL, 0x3FEE1167UL, 0xBD5C7F44UL, 0xBC62B529UL, + 0x337B9B5FUL, 0x3FEDFC97UL, 0x4F184B5CUL, 0xBC81A5CDUL, 0x641C0658UL, 0x3FEDE7D5UL, + 0x8E79BA8FUL, 0xBC8CA552UL, 0xF301B460UL, 0x3FEDD321UL, 0x78F018C3UL, 0x3C82DA57UL, + 0xD63A8315UL, 0x3FEDBE7CUL, 0x926B8BE4UL, 0xBC8B76F1UL, 0x03DB3285UL, 0x3FEDA9E6UL, + 0x696DB532UL, 0x3C8C2300UL, 0x71FF6075UL, 0x3FED955DUL, 0xBB9AF6BEUL, 0x3C8A052DUL, + 0x16C98398UL, 0x3FED80E3UL, 0x8BEDDFE8UL, 0xBC811EC1UL, 0xE862E6D3UL, 0x3FED6C76UL, + 0x4A8165A0UL, 0x3C4FE87AUL, 0xDCFBA487UL, 0x3FED5818UL, 0xD75B3707UL, 0x3C72ED02UL, + 0xEACAA1D6UL, 0x3FED43C8UL, 0xBF5A1614UL, 0x3C83DB53UL, 0x080D89F2UL, 0x3FED2F87UL, + 0x719D8578UL, 0xBC8D487BUL, 0x2B08C968UL, 0x3FED1B53UL, 0x219A36EEUL, 0x3C855636UL, + 0x4A07897CUL, 0x3FED072DUL, 0x43797A9CUL, 0xBC8CBC37UL, 0x5B5BAB74UL, 0x3FECF315UL, + 0xB86DFF57UL, 0xBC8A08E9UL, 0x555DC3FAUL, 0x3FECDF0BUL, 0x53829D72UL, 0xBC7DD83BUL, + 0x2E6D1675UL, 0x3FECCB0FUL, 0x86009093UL, 0xBC6D220FUL, 0xDCEF9069UL, 0x3FECB720UL, + 0xD1E949DCUL, 0x3C6503CBUL, 0x5751C4DBUL, 0x3FECA340UL, 0xD10D08F5UL, 0xBC77F2BEUL, + 0x9406E7B5UL, 0x3FEC8F6DUL, 0x48805C44UL, 0x3C61ACBCUL, 0x8988C933UL, 0x3FEC7BA8UL, + 0xBE255559UL, 0xBC7E76BBUL, 0x2E57D14BUL, 0x3FEC67F1UL, 0xFF483CADUL, 0x3C82884DUL, + 0x78FAFB22UL, 0x3FEC5447UL, 0x2493B5AFUL, 0x3C812F07UL, 0x5FFFD07AUL, 0x3FEC40ABUL, + 0xE083C60AUL, 0x3C8B4537UL, 0xD9FA652CUL, 0x3FEC2D1CUL, 0x17C8A5D7UL, 0xBC86E516UL, + 0xDD85529CUL, 0x3FEC199BUL, 0x895048DDUL, 0x3C711065UL, 0x6141B33DUL, 0x3FEC0628UL, + 0xA1FBCA34UL, 0xBC7D8A5AUL, 0x5BD71E09UL, 0x3FEBF2C2UL, 0x3F6B9C73UL, 0xBC8EFDCAUL, + 0xC3F3A207UL, 0x3FEBDF69UL, 0x60EA5B53UL, 0xBC2C2623UL, 0x904BC1D2UL, 0x3FEBCC1EUL, + 0x7A2D9E84UL, 0x3C723DD0UL, 0xB79A6F1FUL, 0x3FEBB8E0UL, 0xC9696204UL, 0xBC2F52D1UL, + 0x30A1064AUL, 0x3FEBA5B0UL, 0x0E54292EUL, 0xBC8EFCD3UL, 0xF22749E4UL, 0x3FEB928CUL, + 0x54CB65C6UL, 0xBC8B7216UL, 0xF2FB5E47UL, 0x3FEB7F76UL, 0x7E54AC3BUL, 0xBC65584FUL, + 0x29F1C52AUL, 0x3FEB6C6EUL, 0x52883F6EUL, 0x3C82A8F3UL, 0x8DE5593AUL, 0x3FEB5972UL, + 0xBBBA6DE3UL, 0xBC8C71DFUL, 0x15B749B1UL, 0x3FEB4684UL, 0xE9DF7C90UL, 0xBC6F763DUL, + 0xB84F15FBUL, 0x3FEB33A2UL, 0x3084D708UL, 0xBC52805EUL, 0x6C9A8952UL, 0x3FEB20CEUL, + 0x4A0756CCUL, 0x3C84DD02UL, 0x298DB666UL, 0x3FEB0E07UL, 0x4C80E425UL, 0xBC8BDEF5UL, + 0xE622F2FFUL, 0x3FEAFB4CUL, 0x0F315ECDUL, 0xBC84B2FCUL, 0x995AD3ADUL, 0x3FEAE89FUL, + 0x345DCC81UL, 0x3C87A1CDUL, 0x3A3C2774UL, 0x3FEAD5FFUL, 0xB6B1B8E5UL, 0x3C87EF3BUL, + 0xBFD3F37AUL, 0x3FEAC36BUL, 0xCAE76CD0UL, 0xBC7F9234UL, 0x21356EBAUL, 0x3FEAB0E5UL, + 0xDAE94545UL, 0x3C789C31UL, 0x5579FDBFUL, 0x3FEA9E6BUL, 0x0EF7FD31UL, 0x3C80FAC9UL, + 0x53C12E59UL, 0x3FEA8BFEUL, 0xB2BA15A9UL, 0xBC84F867UL, 0x1330B358UL, 0x3FEA799EUL, + 0xCAC563C7UL, 0x3C8BCB7EUL, 0x8AF46052UL, 0x3FEA674AUL, 0x30670366UL, 0x3C550F56UL, + 0xB23E255DUL, 0x3FEA5503UL, 0xDB8D41E1UL, 0xBC8D2F6EUL, 0x80460AD8UL, 0x3FEA42C9UL, + 0x589FB120UL, 0xBC8AA780UL, 0xEC4A2D33UL, 0x3FEA309BUL, 0x7DDC36ABUL, 0x3C86305CUL, + 0xED8EB8BBUL, 0x3FEA1E7AUL, 0xEE8BE70EUL, 0x3C8C6618UL, 0x7B5DE565UL, 0x3FEA0C66UL, + 0x5D1CD533UL, 0xBC835949UL, 0x8D07F29EUL, 0x3FE9FA5EUL, 0xAAF1FACEUL, 0xBC74A9CEUL, + 0x19E32323UL, 0x3FE9E863UL, 0x78E64C6EUL, 0x3C6824CAUL, 0x194BB8D5UL, 0x3FE9D674UL, + 0xA3DD8233UL, 0xBC8516BEUL, 0x82A3F090UL, 0x3FE9C491UL, 0xB071F2BEUL, 0x3C6C7C46UL, + 0x4D53FE0DUL, 0x3FE9B2BBUL, 0x4DF6D518UL, 0xBC8DD84EUL, 0x70CA07BAUL, 0x3FE9A0F1UL, + 0x91CEE632UL, 0xBC8173BDUL, 0xE47A22A2UL, 0x3FE98F33UL, 0xA24C78ECUL, 0x3C6CABDAUL, + 0x9FDE4E50UL, 0x3FE97D82UL, 0x7C1B85D1UL, 0xBC8D185BUL, 0x9A7670B3UL, 0x3FE96BDDUL, + 0x7F19C896UL, 0xBC4BA596UL, 0xCBC8520FUL, 0x3FE95A44UL, 0x96A5F039UL, 0xBC664B7CUL, + 0x2B5F98E5UL, 0x3FE948B8UL, 0x797D2D99UL, 0xBC7DC3D6UL, 0xB0CDC5E5UL, 0x3FE93737UL, + 0x81B57EBCUL, 0xBC575FC7UL, 0x53AA2FE2UL, 0x3FE925C3UL, 0xA639DB7FUL, 0xBC73455FUL, + 0x0B91FFC6UL, 0x3FE9145BUL, 0x2E582524UL, 0xBC8DD679UL, 0xD0282C8AUL, 0x3FE902FEUL, + 0x85FE3FD2UL, 0x3C8592CAUL, 0x99157736UL, 0x3FE8F1AEUL, 0xA2E3976CUL, 0x3C75CC13UL, + 0x5E0866D9UL, 0x3FE8E06AUL, 0x6FC9B2E6UL, 0xBC87114AUL, 0x16B5448CUL, 0x3FE8CF32UL, + 0x32E9E3AAUL, 0xBC60D55EUL, 0xBAD61778UL, 0x3FE8BE05UL, 0xFC43446EUL, 0x3C8ECB5EUL, + 0x422AA0DBUL, 0x3FE8ACE5UL, 0x56864B27UL, 0x3C86E9F1UL, 0xA478580FUL, 0x3FE89BD0UL, + 0x4475202AUL, 0x3C8D5395UL, 0xD98A6699UL, 0x3FE88AC7UL, 0xF37CB53AUL, 0x3C8994C2UL, + 0xD931A436UL, 0x3FE879CAUL, 0xD2DB47BDUL, 0x3C75D2D7UL, 0x9B4492EDUL, 0x3FE868D9UL, + 0x9BD4F6BAUL, 0xBC8FC6F8UL, 0x179F5B21UL, 0x3FE857F4UL, 0xF8B216D0UL, 0xBC4BA748UL, + 0x4623C7ADUL, 0x3FE8471AUL, 0xA341CDFBUL, 0xBC78D684UL, 0x1EB941F7UL, 0x3FE8364CUL, + 0x31DF2BD5UL, 0x3C899B9AUL, 0x994CCE13UL, 0x3FE82589UL, 0xD41532D8UL, 0xBC8D4C1DUL, + 0xADD106D9UL, 0x3FE814D2UL, 0x0D151D4DUL, 0x3C846437UL, 0x543E1A12UL, 0x3FE80427UL, + 0x626D972BUL, 0xBC827C86UL, 0x8491C491UL, 0x3FE7F387UL, 0xCF9311AEUL, 0xBC707F11UL, + 0x36CF4E62UL, 0x3FE7E2F3UL, 0xBA15797EUL, 0x3C605D02UL, 0x62FF86F0UL, 0x3FE7D26AUL, + 0xFB72B8B4UL, 0x3C81BDDBUL, 0x0130C132UL, 0x3FE7C1EDUL, 0xD1164DD6UL, 0x3C8F124CUL, + 0x0976CFDBUL, 0x3FE7B17BUL, 0x8468DC88UL, 0xBC8BEBB5UL, 0x73EB0187UL, 0x3FE7A114UL, + 0xEE04992FUL, 0xBC741577UL, 0x38AC1CF6UL, 0x3FE790B9UL, 0x62AADD3EUL, 0x3C8349A8UL, + 0x4FDE5D3FUL, 0x3FE78069UL, 0x0A02162DUL, 0x3C8866B8UL, 0xB1AB6E09UL, 0x3FE77024UL, + 0x169147F8UL, 0x3C8B7877UL, 0x564267C9UL, 0x3FE75FEBUL, 0x57316DD3UL, 0xBC802459UL, + 0x35D7CBFDUL, 0x3FE74FBDUL, 0x618A6E1CUL, 0x3C8047FDUL, 0x48A58174UL, 0x3FE73F9AUL, + 0x6C65D53CUL, 0xBC80A8D9UL, 0x86EAD08AUL, 0x3FE72F82UL, 0x2CD62C72UL, 0xBC820AA0UL, + 0xE8EC5F74UL, 0x3FE71F75UL, 0x86887A99UL, 0xBC716E47UL, 0x66F42E87UL, 0x3FE70F74UL, + 0xD45AA65FUL, 0x3C49D644UL, 0xF9519484UL, 0x3FE6FF7DUL, 0x25860EF6UL, 0xBC783C0FUL, + 0x98593AE5UL, 0x3FE6EF92UL, 0x9E1AC8B2UL, 0xBC80B974UL, 0x3C651A2FUL, 0x3FE6DFB2UL, + 0x683C88ABUL, 0xBC5BBE3AUL, 0xDDD47645UL, 0x3FE6CFDCUL, 0xB6F17309UL, 0x3C8C7AA9UL, + 0x750BDABFUL, 0x3FE6C012UL, 0x67FF0B0DUL, 0xBC628956UL, 0xFA75173EUL, 0x3FE6B052UL, + 0x2C9A9D0EUL, 0x3C6A38F5UL, 0x667F3BCDUL, 0x3FE6A09EUL, 0x13B26456UL, 0xBC8BDD34UL, + 0xB19E9538UL, 0x3FE690F4UL, 0x9AEB445DUL, 0x3C7804BDUL, 0xD44CA973UL, 0x3FE68155UL, + 0x44F73E65UL, 0x3C5038AEUL, 0xC70833F6UL, 0x3FE671C1UL, 0x586C6134UL, 0xBC7E8732UL, + 0x82552225UL, 0x3FE66238UL, 0x87591C34UL, 0xBC8BB609UL, 0xFEBC8FB7UL, 0x3FE652B9UL, + 0xC9A73E09UL, 0xBC8AE3D5UL, 0x34CCC320UL, 0x3FE64346UL, 0x759D8933UL, 0xBC7C483CUL, + 0x1D1929FDUL, 0x3FE633DDUL, 0xBEB964E5UL, 0x3C884710UL, 0xB03A5585UL, 0x3FE6247EUL, + 0x7E40B497UL, 0xBC8383C1UL, 0xE6CDF6F4UL, 0x3FE6152AUL, 0x4AB84C27UL, 0x3C8E4B3EUL, + 0xB976DC09UL, 0x3FE605E1UL, 0x9B56DE47UL, 0xBC83E242UL, 0x20DCEB71UL, 0x3FE5F6A3UL, + 0xE3CDCF92UL, 0xBC79EADDUL, 0x15AD2148UL, 0x3FE5E76FUL, 0x3080E65EUL, 0x3C8BA6F9UL, + 0x90998B93UL, 0x3FE5D845UL, 0xA8B45643UL, 0xBC8CD6A7UL, 0x8A5946B7UL, 0x3FE5C926UL, + 0x816986A2UL, 0x3C2C4B1BUL, 0xFBA87A03UL, 0x3FE5BA11UL, 0x4C233E1AUL, 0xBC8B77A1UL, + 0xDD485429UL, 0x3FE5AB07UL, 0x054647ADUL, 0x3C86324CUL, 0x27FF07CCUL, 0x3FE59C08UL, + 0xE467E60FUL, 0xBC87E2CEUL, 0xD497C7FDUL, 0x3FE58D12UL, 0x5B9A1DE8UL, 0x3C7295E1UL, + 0xDBE2C4CFUL, 0x3FE57E27UL, 0x8A57B9C4UL, 0xBC80B98CUL, 0x36B527DAUL, 0x3FE56F47UL, + 0x011D93ADUL, 0x3C89BB2CUL, 0xDDE910D2UL, 0x3FE56070UL, 0x168EEBF0UL, 0xBC80FB6EUL, + 0xCA5D920FUL, 0x3FE551A4UL, 0xEFEDE59BUL, 0xBC7D689CUL, 0xF4F6AD27UL, 0x3FE542E2UL, + 0x192D5F7EUL, 0x3C77926DUL, 0x569D4F82UL, 0x3FE5342BUL, 0x1DB13CADUL, 0xBC707ABEUL, + 0xE83F4EEFUL, 0x3FE5257DUL, 0x43EFEF71UL, 0xBC6C998DUL, 0xA2CF6642UL, 0x3FE516DAUL, + 0x69BD93EFUL, 0xBC7F7685UL, 0x7F4531EEUL, 0x3FE50841UL, 0x49B7465FUL, 0x3C6A249BUL, + 0x769D2CA7UL, 0x3FE4F9B2UL, 0xD25957E3UL, 0xBC84B309UL, 0x81D8ABFFUL, 0x3FE4EB2DUL, + 0x2E5D7A52UL, 0xBC85257DUL, 0x99FDDD0DUL, 0x3FE4DCB2UL, 0xBC6A7833UL, 0x3C88ECDBUL, + 0xB817C114UL, 0x3FE4CE41UL, 0x690ABD5DUL, 0x3C805E29UL, 0xD5362A27UL, 0x3FE4BFDAUL, + 0xAFEC42E2UL, 0x3C6D4397UL, 0xEA6DB7D7UL, 0x3FE4B17DUL, 0x7F2897F0UL, 0xBC7125B8UL, + 0xF0D7D3DEUL, 0x3FE4A32AUL, 0xF3D1BE56UL, 0x3C89CB62UL, 0xE192AED2UL, 0x3FE494E1UL, + 0x5E499EA0UL, 0xBC73B289UL, 0xB5C13CD0UL, 0x3FE486A2UL, 0xB69062F0UL, 0x3C63C1A3UL, + 0x668B3237UL, 0x3FE4786DUL, 0xED445733UL, 0xBC8C20F0UL, 0xED1D0057UL, 0x3FE46A41UL, + 0xD1648A76UL, 0x3C8C944BUL, 0x42A7D232UL, 0x3FE45C20UL, 0x82FB1F8EUL, 0xBC586419UL, + 0x6061892DUL, 0x3FE44E08UL, 0x04EF80D0UL, 0x3C389B7AUL, 0x3F84B9D4UL, 0x3FE43FFAUL, + 0x9704C003UL, 0x3C7880BEUL, 0xD950A897UL, 0x3FE431F5UL, 0xE35F7999UL, 0xBC71C7DDUL, + 0x2709468AUL, 0x3FE423FBUL, 0xC0B314DDUL, 0xBC88462DUL, 0x21F72E2AUL, 0x3FE4160AUL, + 0x1C309278UL, 0xBC4EF369UL, 0xC367A024UL, 0x3FE40822UL, 0xB6F4D048UL, 0x3C7BDDF8UL, + 0x04AC801CUL, 0x3FE3FA45UL, 0xF956F9F3UL, 0xBC87D023UL, 0xDF1C5175UL, 0x3FE3EC70UL, + 0x7B8C9BCAUL, 0xBC7AF663UL, 0x4C123422UL, 0x3FE3DEA6UL, 0x11F09EBCUL, 0x3C7ADA09UL, + 0x44EDE173UL, 0x3FE3D0E5UL, 0x8C284C71UL, 0x3C6FE8D0UL, 0xC313A8E5UL, 0x3FE3C32DUL, + 0x375D29C3UL, 0xBC8EFFF8UL, 0xBFEC6CF4UL, 0x3FE3B57FUL, 0xE26FFF18UL, 0x3C854C66UL, + 0x34E59FF7UL, 0x3FE3A7DBUL, 0xD661F5E3UL, 0xBC65E436UL, 0x1B7140EFUL, 0x3FE39A40UL, + 0xFC8E2934UL, 0xBC89A9A5UL, 0x6D05D866UL, 0x3FE38CAEUL, 0x3C9904BDUL, 0xBC8E958DUL, + 0x231E754AUL, 0x3FE37F26UL, 0x9ECEB23CUL, 0xBC89F5CAUL, 0x373AA9CBUL, 0x3FE371A7UL, + 0xBF42EAE2UL, 0xBC863AEAUL, 0xA2DE883BUL, 0x3FE36431UL, 0xA06CB85EUL, 0xBC7C3144UL, + 0x5F929FF1UL, 0x3FE356C5UL, 0x5C4E4628UL, 0xBC7B5CEEUL, 0x66E3FA2DUL, 0x3FE34962UL, + 0x930881A4UL, 0xBC735A75UL, 0xB26416FFUL, 0x3FE33C08UL, 0x843659A6UL, 0x3C832721UL, + 0x3BA8EA32UL, 0x3FE32EB8UL, 0x3CB4F318UL, 0xBC8C45E8UL, 0xFC4CD831UL, 0x3FE32170UL, + 0x8E18047CUL, 0x3C7A9CE7UL, 0xEDEEB2FDUL, 0x3FE31432UL, 0xF3F3FCD1UL, 0x3C7959A3UL, + 0x0A31B715UL, 0x3FE306FEUL, 0xD23182E4UL, 0x3C76F46AUL, 0x4ABD886BUL, 0x3FE2F9D2UL, + 0x532BDA93UL, 0xBC553C55UL, 0xA93E2F56UL, 0x3FE2ECAFUL, 0x45D52383UL, 0x3C61CA0FUL, + 0x1F641589UL, 0x3FE2DF96UL, 0xFBBCE198UL, 0x3C8D16CFUL, 0xA6E4030BUL, 0x3FE2D285UL, + 0x54DB41D5UL, 0x3C800247UL, 0x39771B2FUL, 0x3FE2C57EUL, 0xA6EB5124UL, 0xBC850145UL, + 0xD0DAD990UL, 0x3FE2B87FUL, 0xD6381AA4UL, 0xBC310ADCUL, 0x66D10F13UL, 0x3FE2AB8AUL, + 0x191690A7UL, 0xBC895743UL, 0xF51FDEE1UL, 0x3FE29E9DUL, 0xAFAD1255UL, 0x3C7612E8UL, + 0x7591BB70UL, 0x3FE291BAUL, 0x28401CBDUL, 0xBC72CC72UL, 0xE1F56381UL, 0x3FE284DFUL, + 0x8C3F0D7EUL, 0xBC8A4C3AUL, 0x341DDF29UL, 0x3FE2780EUL, 0x05F9E76CUL, 0x3C8E067CUL, + 0x65E27CDDUL, 0x3FE26B45UL, 0x9940E9D9UL, 0x3C72BD33UL, 0x711ECE75UL, 0x3FE25E85UL, + 0x4AC31B2CUL, 0x3C83E1A2UL, 0x4FB2A63FUL, 0x3FE251CEUL, 0xBEF4F4A4UL, 0x3C7AC155UL, + 0xFB82140AUL, 0x3FE2451FUL, 0x911CA996UL, 0x3C7ACFCCUL, 0x6E756238UL, 0x3FE2387AUL, + 0xB6C70573UL, 0x3C89B07EUL, 0xA27912D1UL, 0x3FE22BDDUL, 0x5577D69FUL, 0x3C7D34FBUL, + 0x917DDC96UL, 0x3FE21F49UL, 0x9494A5EEUL, 0x3C72A97EUL, 0x3578A819UL, 0x3FE212BEUL, + 0x2CFCAAC9UL, 0x3C83592DUL, 0x88628CD6UL, 0x3FE2063BUL, 0x814A8495UL, 0x3C7DC775UL, + 0x8438CE4DUL, 0x3FE1F9C1UL, 0xA097AF5CUL, 0xBC8BF524UL, 0x22FCD91DUL, 0x3FE1ED50UL, + 0x027BB78CUL, 0xBC81DF98UL, 0x5EB44027UL, 0x3FE1E0E7UL, 0x088CB6DEUL, 0xBC86FDD8UL, + 0x3168B9AAUL, 0x3FE1D487UL, 0x00A2643CUL, 0x3C8E016EUL, 0x95281C6BUL, 0x3FE1C82FUL, + 0x8010F8C9UL, 0x3C800977UL, 0x84045CD4UL, 0x3FE1BBE0UL, 0x352EF607UL, 0xBC895386UL, + 0xF8138A1CUL, 0x3FE1AF99UL, 0xA4B69280UL, 0x3C87BF85UL, 0xEB6FCB75UL, 0x3FE1A35BUL, + 0x7B4968E4UL, 0x3C7E5B4CUL, 0x58375D2FUL, 0x3FE19726UL, 0x85F17E08UL, 0x3C84AADDUL, + 0x388C8DEAUL, 0x3FE18AF9UL, 0xD1970F6CUL, 0xBC811023UL, 0x8695BBC0UL, 0x3FE17ED4UL, + 0xE2AC5A64UL, 0x3C609E3FUL, 0x3C7D517BUL, 0x3FE172B8UL, 0xB9D78A76UL, 0xBC719041UL, + 0x5471C3C2UL, 0x3FE166A4UL, 0x82EA1A32UL, 0x3C48F23BUL, 0xC8A58E51UL, 0x3FE15A98UL, + 0xB9EEAB0AUL, 0x3C72406AUL, 0x934F312EUL, 0x3FE14E95UL, 0x39BF44ABUL, 0xBC7B91E8UL, + 0xAEA92DE0UL, 0x3FE1429AUL, 0x9AF1369EUL, 0xBC832FBFUL, 0x14F204ABUL, 0x3FE136A8UL, + 0xBA48DCF0UL, 0xBC57108FUL, 0xC06C31CCUL, 0x3FE12ABDUL, 0xB36CA5C7UL, 0xBC41B514UL, + 0xAB5E2AB6UL, 0x3FE11EDBUL, 0xF703FB72UL, 0xBC8CA454UL, 0xD0125B51UL, 0x3FE11301UL, + 0x39449B3AUL, 0xBC86C510UL, 0x28D7233EUL, 0x3FE10730UL, 0x1692FDD5UL, 0x3C7D46EBUL, + 0xAFFED31BUL, 0x3FE0FB66UL, 0xC44EBD7BUL, 0xBC5B9BEDUL, 0x5FDFA9C5UL, 0x3FE0EFA5UL, + 0xBC54021BUL, 0xBC849DB9UL, 0x32D3D1A2UL, 0x3FE0E3ECUL, 0x27C57B52UL, 0x3C303A17UL, + 0x23395DECUL, 0x3FE0D83BUL, 0xE43F316AUL, 0xBC8BC14DUL, 0x2B7247F7UL, 0x3FE0CC92UL, + 0x16E24F71UL, 0x3C801EDCUL, 0x45E46C85UL, 0x3FE0C0F1UL, 0x06D21CEFUL, 0x3C84F989UL, + 0x6CF9890FUL, 0x3FE0B558UL, 0x4ADC610BUL, 0x3C88A62EUL, 0x9B1F3919UL, 0x3FE0A9C7UL, + 0x873D1D38UL, 0x3C75D16CUL, 0xCAC6F383UL, 0x3FE09E3EUL, 0x18316136UL, 0x3C814878UL, + 0xF66607E0UL, 0x3FE092BDUL, 0x800A3FD1UL, 0xBC868063UL, 0x18759BC8UL, 0x3FE08745UL, + 0x4BB284FFUL, 0x3C5186BEUL, 0x2B72A836UL, 0x3FE07BD4UL, 0x54458700UL, 0x3C732334UL, + 0x29DDF6DEUL, 0x3FE0706BUL, 0xE2B13C27UL, 0xBC7C91DFUL, 0x0E3C1F89UL, 0x3FE0650AUL, + 0x5799C397UL, 0xBC85CB7BUL, 0xD3158574UL, 0x3FE059B0UL, 0xA475B465UL, 0x3C7D73E2UL, + 0x72F654B1UL, 0x3FE04E5FUL, 0x3AA0D08CUL, 0x3C74C379UL, 0xE86E7F85UL, 0x3FE04315UL, + 0x1977C96EUL, 0xBC80A31CUL, 0x2E11BBCCUL, 0x3FE037D4UL, 0xEEADE11AUL, 0x3C556811UL, + 0x3E778061UL, 0x3FE02C9AUL, 0x535B085DUL, 0xBC619083UL, 0x143B0281UL, 0x3FE02168UL, + 0x0FC54EB6UL, 0xBC72BF31UL, 0xA9FB3335UL, 0x3FE0163DUL, 0x9AB8CDB7UL, 0x3C8B6129UL, + 0xFA5ABCBFUL, 0x3FE00B1AUL, 0xA7609F71UL, 0xBC74F6B2UL }; #define __ _masm-> From 0366d8823bc844225ca24964e352ce0a57d01683 Mon Sep 17 00:00:00 2001 From: SendaoYan Date: Wed, 1 Oct 2025 00:52:30 +0000 Subject: [PATCH 0012/1639] 8354894: java/lang/Thread/virtual/Starvation.java timeout on server with high CPUs Co-authored-by: Alan Bateman Reviewed-by: jpai --- test/jdk/java/lang/Thread/virtual/Starvation.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/test/jdk/java/lang/Thread/virtual/Starvation.java b/test/jdk/java/lang/Thread/virtual/Starvation.java index c55ad3c2494..987c54c1a0c 100644 --- a/test/jdk/java/lang/Thread/virtual/Starvation.java +++ b/test/jdk/java/lang/Thread/virtual/Starvation.java @@ -25,7 +25,7 @@ * @requires vm.continuations * @library /test/lib * @bug 8345294 - * @run main/othervm/timeout=800/native --enable-native-access=ALL-UNNAMED Starvation 100000 + * @run main/othervm/native --enable-native-access=ALL-UNNAMED Starvation */ import java.time.Duration; @@ -37,9 +37,16 @@ import jdk.test.lib.thread.VThreadPinner; public class Starvation { public static void main(String[] args) throws Exception { - int iterations = Integer.parseInt(args[0]); + int iterations; + if (args.length > 0) { + iterations = Integer.parseInt(args[0]); + } else { + int nprocs = Runtime.getRuntime().availableProcessors(); + iterations = 40_000 / nprocs; + } - for (int i = 0; i < iterations; i++) { + for (int i = 1; i <= iterations; i++) { + System.out.format("%s iteration %d of %d ...%n", Instant.now(), i, iterations); var exRef = new AtomicReference(); Thread thread = Thread.startVirtualThread(() -> { try { From 17d8fa8e421db67027c9e7d2ddd634ff0b897cb6 Mon Sep 17 00:00:00 2001 From: Jaikiran Pai Date: Wed, 1 Oct 2025 01:40:06 +0000 Subject: [PATCH 0013/1639] 8367026: Reorder the timeout failure handler commands to have jstack run before the rest Reviewed-by: erikj, lmesnik --- .../src/share/conf/common.properties | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/test/failure_handler/src/share/conf/common.properties b/test/failure_handler/src/share/conf/common.properties index 5cd2c1c13ca..295a7458d4b 100644 --- a/test/failure_handler/src/share/conf/common.properties +++ b/test/failure_handler/src/share/conf/common.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,13 @@ args=%p ################################################################################ # process info to gather ################################################################################ +# It's important to retain the order of these actions and run the thread dump +# generating commands before the rest, to allow for capturing the test +# process' call stack as soon as the timeout has occurred. That reduces the chances +# of the test completing and thus missing crucial details from the thread dump +# while these timeout actions were being run. onTimeout=\ + thread_dump \ jinfo \ jcmd.compiler.codecache jcmd.compiler.codelist \ jcmd.compiler.queue \ @@ -63,9 +69,13 @@ jcmd.thread.dump_to_file.params.successArtifacts=JavaThread.dump.%p.%iterCount jcmd.thread.vthread_scheduler.args=%p Thread.vthread_scheduler +# use jstack to generate one thread dump +thread_dump.app=jstack +thread_dump.args=-e -l %p + jstack.app=jstack jstack.args=-e -l %p -jstack.params.repeat=6 +jstack.params.repeat=5 jhsdb.app=jhsdb jhsdb.jstack.live.default.args=jstack --pid %p From 8c3ca024c770d3cf3b35234e967e5f0f0d610388 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Wed, 1 Oct 2025 03:58:49 +0000 Subject: [PATCH 0014/1639] 8368817: Convert JDK_Version::to_string to use stringStream instead of jio_snprintf-chain Reviewed-by: fandreuzzi, jsjolen --- src/hotspot/share/runtime/java.cpp | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/src/hotspot/share/runtime/java.cpp b/src/hotspot/share/runtime/java.cpp index 9363f9055ba..6fda21ac86c 100644 --- a/src/hotspot/share/runtime/java.cpp +++ b/src/hotspot/share/runtime/java.cpp @@ -747,29 +747,19 @@ int JDK_Version::compare(const JDK_Version& other) const { /* See JEP 223 */ void JDK_Version::to_string(char* buffer, size_t buflen) const { - assert(buffer && buflen > 0, "call with useful buffer"); - size_t index = 0; - + assert((buffer != nullptr) && (buflen > 0), "call with useful buffer"); + stringStream ss{buffer, buflen}; if (!is_valid()) { - jio_snprintf(buffer, buflen, "%s", "(uninitialized)"); + ss.print_raw("(uninitialized)"); } else { - int rc = jio_snprintf( - &buffer[index], buflen - index, "%d.%d", _major, _minor); - if (rc == -1) return; - index += rc; + ss.print("%d.%d", _major, _minor); if (_patch > 0) { - rc = jio_snprintf(&buffer[index], buflen - index, ".%d.%d", _security, _patch); - if (rc == -1) return; - index += rc; + ss.print(".%d.%d", _security, _patch); } else if (_security > 0) { - rc = jio_snprintf(&buffer[index], buflen - index, ".%d", _security); - if (rc == -1) return; - index += rc; + ss.print(".%d", _security); } if (_build > 0) { - rc = jio_snprintf(&buffer[index], buflen - index, "+%d", _build); - if (rc == -1) return; - index += rc; + ss.print("+%d", _build); } } } From 394eb80a48fa73238cf897087b99c3da5a616566 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Wed, 1 Oct 2025 06:12:05 +0000 Subject: [PATCH 0015/1639] 8368957: Remove metaprogramming/logical.hpp in favor of C++17 facilities Reviewed-by: mchevalier, iwalulya --- src/hotspot/share/gc/shared/workerUtils.hpp | 7 +- src/hotspot/share/metaprogramming/logical.hpp | 64 ------------- .../gtest/metaprogramming/test_logical.cpp | 90 ------------------- 3 files changed, 4 insertions(+), 157 deletions(-) delete mode 100644 src/hotspot/share/metaprogramming/logical.hpp delete mode 100644 test/hotspot/gtest/metaprogramming/test_logical.cpp diff --git a/src/hotspot/share/gc/shared/workerUtils.hpp b/src/hotspot/share/gc/shared/workerUtils.hpp index 223dfb34eb2..5f167ffb6b2 100644 --- a/src/hotspot/share/gc/shared/workerUtils.hpp +++ b/src/hotspot/share/gc/shared/workerUtils.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,11 +27,12 @@ #include "memory/allocation.hpp" #include "metaprogramming/enableIf.hpp" -#include "metaprogramming/logical.hpp" #include "runtime/mutex.hpp" #include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" +#include + // A class that acts as a synchronisation barrier. Workers enter // the barrier and must wait until all other workers have entered // before any of them may leave. @@ -103,7 +104,7 @@ public: // explicitly passed as extra arguments. Every thread in the parallel task // must execute this. template...>::value)> + ENABLE_IF(std::conjunction_v...>)> void all_tasks_claimed(T0 first_skipped, Ts... more_skipped) { static_assert(std::is_convertible::value, "not convertible"); uint skipped[] = { static_cast(first_skipped), static_cast(more_skipped)... }; diff --git a/src/hotspot/share/metaprogramming/logical.hpp b/src/hotspot/share/metaprogramming/logical.hpp deleted file mode 100644 index a488b94f8b9..00000000000 --- a/src/hotspot/share/metaprogramming/logical.hpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * 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. - * - */ - -#ifndef SHARE_METAPROGRAMMING_LOGICAL_HPP -#define SHARE_METAPROGRAMMING_LOGICAL_HPP - -// Stand-ins for C++17 logical operations on types. - -#include - -// Stand-in for C++17 std::bool_constant. -template -using BoolConstant = std::integral_constant; - -// Stand-in for C++17 std::conjunction -template -struct Conjunction : public std::true_type {}; - -template -struct Conjunction : public T1 {}; - -template -struct Conjunction : - public std::conditional_t, T1> -{}; - -// Stand-in for C++17 std::disjunction. -template -struct Disjunction : public std::false_type {}; - -template -struct Disjunction : public T1 {}; - -template -struct Disjunction : - public std::conditional_t> -{}; - -// Stand-in for C++17 std::negation. -template -using Negation = BoolConstant; - -#endif // SHARE_METAPROGRAMMING_LOGICAL_HPP diff --git a/test/hotspot/gtest/metaprogramming/test_logical.cpp b/test/hotspot/gtest/metaprogramming/test_logical.cpp deleted file mode 100644 index 8f2f1940a2b..00000000000 --- a/test/hotspot/gtest/metaprogramming/test_logical.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "metaprogramming/logical.hpp" -#include - -class TestBoolConstant { - static_assert(BoolConstant::value, "true"); - static_assert(!BoolConstant::value, "false"); -}; - -class TestConjunction { - class A : public std::true_type {}; - class B : public std::true_type {}; - class C : public std::false_type {}; - class D : public std::false_type {}; - - static_assert(Conjunction<>::value, "nullary value"); - - static_assert(Conjunction::value, "true value"); - static_assert(std::is_base_of>::value, "true type"); - - static_assert(!Conjunction::value, "false value"); - static_assert(std::is_base_of>::value, "false type"); - - static_assert(Conjunction::value, "true/true value"); - static_assert(std::is_base_of>::value, "true/true type"); - - static_assert(!Conjunction::value, "true/false value"); - static_assert(std::is_base_of>::value, "true/false type"); - - static_assert(!Conjunction::value, "false/true value"); - static_assert(std::is_base_of>::value, "false/true type"); - - static_assert(!Conjunction::value, "false/false value"); - static_assert(std::is_base_of>::value, "false/false type"); -}; - -class TestDisjunction { - class A : public std::true_type {}; - class B : public std::true_type {}; - class C : public std::false_type {}; - class D : public std::false_type {}; - - static_assert(!Disjunction<>::value, "nullary value"); - - static_assert(Disjunction::value, "true value"); - static_assert(std::is_base_of>::value, "true type"); - - static_assert(!Disjunction::value, "false value"); - static_assert(std::is_base_of>::value, "false type"); - - static_assert(Disjunction::value, "true/true value"); - static_assert(std::is_base_of>::value, "true/true type"); - - static_assert(Disjunction::value, "true/false value"); - static_assert(std::is_base_of>::value, "true/false type"); - - static_assert(Disjunction::value, "false/true value"); - static_assert(std::is_base_of>::value, "false/true type"); - - static_assert(!Disjunction::value, "false/false value"); - static_assert(std::is_base_of>::value, "false/false type"); -}; - -class TestNegation { - static_assert(Negation::value, "false -> true"); - static_assert(!Negation::value, "true -> false"); -}; From 1188ca55f525554d2bb10691b368c818d98e5ea7 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Wed, 1 Oct 2025 08:07:59 +0000 Subject: [PATCH 0016/1639] 8368954: G1: Document why G1 uses TLS storage for the current card table reference Reviewed-by: ayang, rcastanedalo, iwalulya --- src/hotspot/share/gc/g1/g1ThreadLocalData.hpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/hotspot/share/gc/g1/g1ThreadLocalData.hpp b/src/hotspot/share/gc/g1/g1ThreadLocalData.hpp index 858081b0581..07c8c569504 100644 --- a/src/hotspot/share/gc/g1/g1ThreadLocalData.hpp +++ b/src/hotspot/share/gc/g1/g1ThreadLocalData.hpp @@ -36,6 +36,15 @@ class G1ThreadLocalData { private: SATBMarkQueue _satb_mark_queue; + // The current base address of the card table. Accessed by the barrier to do + // the card mark. Changed as required by the refinement control thread to + // implement card table switching. + // + // Tests showed that embedding this value in the TLS block is the cheapest + // way for fast access to this value in the barrier. + // E.g. embedding an address to that value directly into the code stream and + // then loading from that was found to be slower on non-x64 architectures. + // Additionally it increases code size a lot. G1CardTable::CardValue* _byte_map_base; // Per-thread cache of pinned object count to reduce atomic operation traffic From 6c2d383492d194eb8a604a58a0336c371cbb1ea5 Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Wed, 1 Oct 2025 08:08:19 +0000 Subject: [PATCH 0017/1639] 8368953: Document the reason why Serial/Parallel/G1 use zero as dirty card value Co-authored-by: Albert Mingkun Yang Reviewed-by: ayang, iwalulya --- src/hotspot/share/gc/shared/cardTable.hpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/hotspot/share/gc/shared/cardTable.hpp b/src/hotspot/share/gc/shared/cardTable.hpp index 63dcfe7aecb..ab26055e522 100644 --- a/src/hotspot/share/gc/shared/cardTable.hpp +++ b/src/hotspot/share/gc/shared/cardTable.hpp @@ -61,6 +61,20 @@ protected: inline size_t compute_byte_map_size(size_t num_bytes); + // We use 0x00 (zero) to represent Dirty and 0xFF to represent Clean because + // this choice reduces the barrier code by one instruction on architectures with + // a constant-zero register. On such architectures, the Dirty value (0x00) is + // directly accessible through the zero register, eliminating the need to load + // the value explicitly and thereby saving one instruction + // + // E.g. see + // Urs Hölzle. A fast write barrier for generational garbage collectors. + // In Eliot Moss, Paul R. Wilson, and Benjamin Zorn, editors, OOPSLA/ECOOP '93 + // Workshop on Garbage Collection in Object-Oriented Systems, October 1993 + // + // that shows this for SPARC (but aarch32/aarch64/RISC-V are similar in this + // respect). + // enum CardValues { clean_card = (CardValue)-1, From f49849a5ed4e9383e39e69ce76bb8ea74fb443f9 Mon Sep 17 00:00:00 2001 From: Hamlin Li Date: Wed, 1 Oct 2025 08:22:02 +0000 Subject: [PATCH 0018/1639] 8368893: RISC-V: crash after JDK-8352673 on fastdebug version Reviewed-by: fyang, dzhang --- src/hotspot/cpu/riscv/vm_version_riscv.cpp | 9 ++------- .../os_cpu/linux_riscv/vm_version_linux_riscv.cpp | 1 - 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.cpp b/src/hotspot/cpu/riscv/vm_version_riscv.cpp index 9d6ac4963aa..53f7ff9bc66 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.cpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.cpp @@ -213,13 +213,8 @@ void VM_Version::common_initialize() { } if (UseRVV) { - if (!ext_V.enabled() && FLAG_IS_DEFAULT(UseRVV)) { - warning("RVV is not supported on this CPU"); - FLAG_SET_DEFAULT(UseRVV, false); - } else { - // read vector length from vector CSR vlenb - _initial_vector_length = cpu_vector_length(); - } + // read vector length from vector CSR vlenb + _initial_vector_length = cpu_vector_length(); } // Misc Intrinsics that could depend on RVV. diff --git a/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp b/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp index 89501aac979..67d405f0656 100644 --- a/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp +++ b/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp @@ -100,7 +100,6 @@ #endif uint32_t VM_Version::cpu_vector_length() { - assert(ext_V.enabled(), "should not call this"); return (uint32_t)read_csr(CSR_VLENB); } From 84e5d63b9fa8af0b35e1d682a81900cb157697fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Sj=C3=B6len?= Date: Wed, 1 Oct 2025 09:01:19 +0000 Subject: [PATCH 0019/1639] 8368885: NMT CommandLine tests can check for error better Reviewed-by: phubner, azafari, shade --- .../jtreg/runtime/NMT/CommandLineDetail.java | 21 ++++++++++--------- .../jtreg/runtime/NMT/CommandLineSummary.java | 21 ++++++++++--------- 2 files changed, 22 insertions(+), 20 deletions(-) diff --git a/test/hotspot/jtreg/runtime/NMT/CommandLineDetail.java b/test/hotspot/jtreg/runtime/NMT/CommandLineDetail.java index 57f2302db30..a7561c7792e 100644 --- a/test/hotspot/jtreg/runtime/NMT/CommandLineDetail.java +++ b/test/hotspot/jtreg/runtime/NMT/CommandLineDetail.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,13 +35,14 @@ import jdk.test.lib.process.OutputAnalyzer; public class CommandLineDetail { - public static void main(String args[]) throws Exception { - - ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder( - "-XX:NativeMemoryTracking=detail", - "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); - output.shouldNotContain("error"); - output.shouldHaveExitValue(0); - } + public static void main(String args[]) throws Exception { + ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder( + "-Xlog:nmt=warning", + "-XX:NativeMemoryTracking=detail", + "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("NMT initialization failed"); + output.shouldNotContain("Could not create the Java Virtual Machine."); + output.shouldHaveExitValue(0); + } } diff --git a/test/hotspot/jtreg/runtime/NMT/CommandLineSummary.java b/test/hotspot/jtreg/runtime/NMT/CommandLineSummary.java index 02b37a40ef4..381fe3eba34 100644 --- a/test/hotspot/jtreg/runtime/NMT/CommandLineSummary.java +++ b/test/hotspot/jtreg/runtime/NMT/CommandLineSummary.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,13 +35,14 @@ import jdk.test.lib.process.OutputAnalyzer; public class CommandLineSummary { - public static void main(String args[]) throws Exception { - - ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder( - "-XX:NativeMemoryTracking=summary", - "-version"); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); - output.shouldNotContain("error"); - output.shouldHaveExitValue(0); - } + public static void main(String args[]) throws Exception { + ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder( + "-Xlog:nmt=warning", + "-XX:NativeMemoryTracking=summary", + "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("NMT initialization failed"); + output.shouldNotContain("Could not create the Java Virtual Machine."); + output.shouldHaveExitValue(0); + } } From 5a2700f231d72e2241703c1d17b308f031e8566c Mon Sep 17 00:00:00 2001 From: Richard Reingruber Date: Wed, 1 Oct 2025 09:26:43 +0000 Subject: [PATCH 0020/1639] 8368861: [TEST] compiler/floatingpoint/ScalarFPtoIntCastTest.java expects x86 IR on non-x86 platforms Reviewed-by: sviswanathan, mdoerr --- .../compiler/floatingpoint/ScalarFPtoIntCastTest.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/hotspot/jtreg/compiler/floatingpoint/ScalarFPtoIntCastTest.java b/test/hotspot/jtreg/compiler/floatingpoint/ScalarFPtoIntCastTest.java index e6d1c875250..e8575cfe6b6 100644 --- a/test/hotspot/jtreg/compiler/floatingpoint/ScalarFPtoIntCastTest.java +++ b/test/hotspot/jtreg/compiler/floatingpoint/ScalarFPtoIntCastTest.java @@ -88,6 +88,7 @@ public class ScalarFPtoIntCastTest { @Test @IR(counts = {IRNode.CONV_F2I, "> 0"}) @IR(counts = {IRNode.X86_SCONV_F2I, "> 0"}, + applyIfPlatform = {"x64", "true"}, applyIfCPUFeature = {"avx10_2", "false"}) @IR(counts = {IRNode.X86_SCONV_F2I_AVX10, "> 0"}, applyIfCPUFeature = {"avx10_2", "true"}) @@ -103,6 +104,7 @@ public class ScalarFPtoIntCastTest { @Test @IR(counts = {IRNode.CONV_F2L, "> 0"}) @IR(counts = {IRNode.X86_SCONV_F2L, "> 0"}, + applyIfPlatform = {"x64", "true"}, applyIfCPUFeature = {"avx10_2", "false"}) @IR(counts = {IRNode.X86_SCONV_F2L_AVX10, "> 0"}, applyIfCPUFeature = {"avx10_2", "true"}) @@ -118,6 +120,7 @@ public class ScalarFPtoIntCastTest { @Test @IR(counts = {IRNode.CONV_F2I, "> 0"}) @IR(counts = {IRNode.X86_SCONV_F2I, "> 0"}, + applyIfPlatform = {"x64", "true"}, applyIfCPUFeature = {"avx10_2", "false"}) @IR(counts = {IRNode.X86_SCONV_F2I_AVX10, "> 0"}, applyIfCPUFeature = {"avx10_2", "true"}) @@ -133,6 +136,7 @@ public class ScalarFPtoIntCastTest { @Test @IR(counts = {IRNode.CONV_F2I, "> 0"}) @IR(counts = {IRNode.X86_SCONV_F2I, "> 0"}, + applyIfPlatform = {"x64", "true"}, applyIfCPUFeature = {"avx10_2", "false"}) @IR(counts = {IRNode.X86_SCONV_F2I_AVX10, "> 0"}, applyIfCPUFeature = {"avx10_2", "true"}) @@ -148,6 +152,7 @@ public class ScalarFPtoIntCastTest { @Test @IR(counts = {IRNode.CONV_D2I, "> 0"}) @IR(counts = {IRNode.X86_SCONV_D2I, "> 0"}, + applyIfPlatform = {"x64", "true"}, applyIfCPUFeature = {"avx10_2", "false"}) @IR(counts = {IRNode.X86_SCONV_D2I_AVX10, "> 0"}, applyIfCPUFeature = {"avx10_2", "true"}) @@ -163,6 +168,7 @@ public class ScalarFPtoIntCastTest { @Test @IR(counts = {IRNode.CONV_D2L, "> 0"}) @IR(counts = {IRNode.X86_SCONV_D2L, "> 0"}, + applyIfPlatform = {"x64", "true"}, applyIfCPUFeature = {"avx10_2", "false"}) @IR(counts = {IRNode.X86_SCONV_D2L_AVX10, "> 0"}, applyIfCPUFeature = {"avx10_2", "true"}) @@ -178,6 +184,7 @@ public class ScalarFPtoIntCastTest { @Test @IR(counts = {IRNode.CONV_D2I, "> 0"}) @IR(counts = {IRNode.X86_SCONV_D2I, "> 0"}, + applyIfPlatform = {"x64", "true"}, applyIfCPUFeature = {"avx10_2", "false"}) @IR(counts = {IRNode.X86_SCONV_D2I_AVX10, "> 0"}, applyIfCPUFeature = {"avx10_2", "true"}) @@ -193,6 +200,7 @@ public class ScalarFPtoIntCastTest { @Test @IR(counts = {IRNode.CONV_D2I, "> 0"}) @IR(counts = {IRNode.X86_SCONV_D2I, "> 0"}, + applyIfPlatform = {"x64", "true"}, applyIfCPUFeature = {"avx10_2", "false"}) @IR(counts = {IRNode.X86_SCONV_D2I_AVX10, "> 0"}, applyIfCPUFeature = {"avx10_2", "true"}) From 3607e9986f1582ebdae1b6ad2a13c1a9c239e0d6 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Wed, 1 Oct 2025 11:16:44 +0000 Subject: [PATCH 0021/1639] 8367279: Test tools/javac/tree/TreePosTest.java timed out Reviewed-by: asotona --- .../tools/javac/tree/TreePosTest.java | 44 +++++++++---------- 1 file changed, 21 insertions(+), 23 deletions(-) diff --git a/test/langtools/tools/javac/tree/TreePosTest.java b/test/langtools/tools/javac/tree/TreePosTest.java index 0ae62ca940d..9e6dcf61306 100644 --- a/test/langtools/tools/javac/tree/TreePosTest.java +++ b/test/langtools/tools/javac/tree/TreePosTest.java @@ -38,16 +38,11 @@ import java.io.IOException; import java.io.PrintStream; import java.io.PrintWriter; import java.io.StringWriter; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.nio.charset.Charset; +import java.io.UncheckedIOException; import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; -import java.util.Map; import java.util.Set; import javax.swing.DefaultComboBoxModel; import javax.swing.JComboBox; @@ -71,7 +66,7 @@ import javax.tools.StandardJavaFileManager; import com.sun.source.tree.CaseTree.CaseKind; import com.sun.source.tree.CompilationUnitTree; -import com.sun.source.util.JavacTask; +import com.sun.tools.javac.api.JavacTaskPool; import com.sun.tools.javac.api.JavacTool; import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.tree.EndPosTable; @@ -80,7 +75,6 @@ import com.sun.tools.javac.tree.JCTree.JCAnnotatedType; import com.sun.tools.javac.tree.JCTree.JCCase; import com.sun.tools.javac.tree.JCTree.JCClassDecl; import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; -import com.sun.tools.javac.tree.JCTree.JCImport; import com.sun.tools.javac.tree.JCTree.JCImportBase; import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCNewClass; @@ -90,7 +84,6 @@ import com.sun.tools.javac.tree.TreeScanner; import static com.sun.tools.javac.tree.JCTree.Tag.*; import static com.sun.tools.javac.util.Position.NOPOS; -import java.util.stream.Stream; /** * Utility and test program to check validity of tree positions for tree nodes. @@ -275,6 +268,7 @@ public class TreePosTest { PrintWriter pw = new PrintWriter(sw); Reporter r = new Reporter(pw); JavacTool tool = JavacTool.create(); + JavacTaskPool pool = new JavacTaskPool(1); StandardJavaFileManager fm = tool.getStandardFileManager(r, null, null); /** @@ -285,21 +279,25 @@ public class TreePosTest { * @throws TreePosTest.ParseException if any errors occur while parsing the file */ JCCompilationUnit read(File file) throws IOException, ParseException { - JavacTool tool = JavacTool.create(); r.errors = 0; Iterable files = fm.getJavaFileObjects(file); - JavacTask task = tool.getTask(pw, fm, r, List.of("-proc:none"), null, files); - Iterable trees = task.parse(); - pw.flush(); - if (r.errors > 0) - throw new ParseException(sw.toString()); - Iterator iter = trees.iterator(); - if (!iter.hasNext()) - throw new Error("no trees found"); - JCCompilationUnit t = (JCCompilationUnit) iter.next(); - if (iter.hasNext()) - throw new Error("too many trees found"); - return t; + return pool.getTask(pw, fm, r, List.of("-proc:none"), null, files, task -> { + try { + Iterable trees = task.parse(); + pw.flush(); + if (r.errors > 0) + throw new ParseException(sw.toString()); + Iterator iter = trees.iterator(); + if (!iter.hasNext()) + throw new Error("no trees found"); + JCCompilationUnit t = (JCCompilationUnit) iter.next(); + if (iter.hasNext()) + throw new Error("too many trees found"); + return t; + } catch (IOException ex) { + throw new UncheckedIOException(ex); + } + }); } /** @@ -546,7 +544,7 @@ public class TreePosTest { /** * Thrown when errors are found parsing a java file. */ - private static class ParseException extends Exception { + private static class ParseException extends RuntimeException { ParseException(String msg) { super(msg); } From c69456e87aeb8653ce23bc7f579c254511bbf2d1 Mon Sep 17 00:00:00 2001 From: Justin King Date: Wed, 1 Oct 2025 13:23:13 +0000 Subject: [PATCH 0022/1639] 8368962: hotspot/cpu/aarch64/bytecodes_aarch64.{hpp,cpp} is unused Reviewed-by: aph, mhaessig --- src/hotspot/cpu/aarch64/bytecodes_aarch64.cpp | 28 ----------------- src/hotspot/cpu/aarch64/bytecodes_aarch64.hpp | 31 ------------------- 2 files changed, 59 deletions(-) delete mode 100644 src/hotspot/cpu/aarch64/bytecodes_aarch64.cpp delete mode 100644 src/hotspot/cpu/aarch64/bytecodes_aarch64.hpp diff --git a/src/hotspot/cpu/aarch64/bytecodes_aarch64.cpp b/src/hotspot/cpu/aarch64/bytecodes_aarch64.cpp deleted file mode 100644 index 119ad8baec3..00000000000 --- a/src/hotspot/cpu/aarch64/bytecodes_aarch64.cpp +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2014, Red Hat Inc. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - * - */ - -#include "interpreter/bytecodes.hpp" - - diff --git a/src/hotspot/cpu/aarch64/bytecodes_aarch64.hpp b/src/hotspot/cpu/aarch64/bytecodes_aarch64.hpp deleted file mode 100644 index 1daf71388e3..00000000000 --- a/src/hotspot/cpu/aarch64/bytecodes_aarch64.hpp +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2014, Red Hat Inc. 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. - * - */ - -#ifndef CPU_AARCH64_BYTECODES_AARCH64_HPP -#define CPU_AARCH64_BYTECODES_AARCH64_HPP - -// No aarch64 specific bytecodes - -#endif // CPU_AARCH64_BYTECODES_AARCH64_HPP From 182fbc2b836d27410ccd0da512acb17bac9363c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20Casta=C3=B1eda=20Lozano?= Date: Wed, 1 Oct 2025 13:55:18 +0000 Subject: [PATCH 0023/1639] 8368675: IGV: nodes are wrongly marked as changed in the difference view Reviewed-by: mchevalier, mhaessig, dfenacci, tholenstein --- .../com/sun/hotspot/igv/data/InputNode.java | 22 +++++++++++++++---- .../igv/data/serialization/Parser.java | 4 ++-- .../hotspot/igv/difference/Difference.java | 4 ++-- .../com/sun/hotspot/igv/graph/Figure.java | 4 ++-- .../sun/hotspot/igv/view/NodeQuickSearch.java | 4 +--- 5 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/InputNode.java b/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/InputNode.java index 48a000bf7b9..df1cbbacc0c 100644 --- a/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/InputNode.java +++ b/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/InputNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,9 @@ import java.util.Objects; */ public class InputNode extends Properties.Entity { + public static final String LABEL_PROPERTY = "label"; + public static final String COLOR_PROPERTY = "color"; + private int id; public InputNode(InputNode n) { @@ -51,6 +54,17 @@ public class InputNode extends Properties.Entity { return id; } + // Return the node properties that are present in the input graph, excluding + // properties computed by IGV itself. This is useful e.g. to produce the + // difference view, where nodes should be compared based only on their + // intrinsic characteristics. + public Properties getPrimaryProperties() { + Properties primaryProperties = new Properties(getProperties()); + primaryProperties.setProperty(LABEL_PROPERTY, null); + primaryProperties.setProperty(COLOR_PROPERTY, null); + return primaryProperties; + } + @Override public boolean equals(Object obj) { if (this == obj) { @@ -72,14 +86,14 @@ public class InputNode extends Properties.Entity { public void setCustomColor(Color color) { if (color != null) { String hexColor = String.format("#%08X", color.getRGB()); - getProperties().setProperty("color", hexColor); + getProperties().setProperty(COLOR_PROPERTY, hexColor); } else { - getProperties().setProperty("color", null); + getProperties().setProperty(COLOR_PROPERTY, null); } } public Color getCustomColor() { - String hexColor = getProperties().get("color"); + String hexColor = getProperties().get(COLOR_PROPERTY); if (hexColor != null) { try { String hex = hexColor.startsWith("#") ? hexColor.substring(1) : hexColor; diff --git a/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/serialization/Parser.java b/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/serialization/Parser.java index dfe60372eda..06887ba22f4 100644 --- a/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/serialization/Parser.java +++ b/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/serialization/Parser.java @@ -81,7 +81,7 @@ public class Parser implements GraphParser { public static final String FROM_INDEX_PROPERTY = "fromIndex"; public static final String TO_INDEX_PROPERTY = "toIndex"; public static final String TO_INDEX_ALT_PROPERTY = "index"; - public static final String LABEL_PROPERTY = "label"; + public static final String EDGE_LABEL_PROPERTY = "label"; public static final String METHOD_ELEMENT = "method"; public static final String INLINE_ELEMENT = "inline"; public static final String BYTECODES_ELEMENT = "bytecodes"; @@ -655,7 +655,7 @@ public class Parser implements GraphParser { toIndex = Integer.parseInt(toIndexString); } - label = readAttribute(LABEL_PROPERTY); + label = readAttribute(EDGE_LABEL_PROPERTY); type = readAttribute(TYPE_PROPERTY); from = lookupID(readRequiredAttribute(FROM_PROPERTY)); diff --git a/src/utils/IdealGraphVisualizer/Difference/src/main/java/com/sun/hotspot/igv/difference/Difference.java b/src/utils/IdealGraphVisualizer/Difference/src/main/java/com/sun/hotspot/igv/difference/Difference.java index c904e8c6083..89b1434663f 100644 --- a/src/utils/IdealGraphVisualizer/Difference/src/main/java/com/sun/hotspot/igv/difference/Difference.java +++ b/src/utils/IdealGraphVisualizer/Difference/src/main/java/com/sun/hotspot/igv/difference/Difference.java @@ -356,7 +356,7 @@ public class Difference { private static void markAsChanged(InputNode n, InputNode firstNode, InputNode otherNode) { boolean difference = false; - for (Property p : otherNode.getProperties()) { + for (Property p : otherNode.getPrimaryProperties()) { String s = firstNode.getProperties().get(p.getName()); if (!p.getValue().equals(s)) { difference = true; @@ -364,7 +364,7 @@ public class Difference { } } - for (Property p : firstNode.getProperties()) { + for (Property p : firstNode.getPrimaryProperties()) { String s = otherNode.getProperties().get(p.getName()); if (s == null && p.getValue().length() > 0) { difference = true; diff --git a/src/utils/IdealGraphVisualizer/Graph/src/main/java/com/sun/hotspot/igv/graph/Figure.java b/src/utils/IdealGraphVisualizer/Graph/src/main/java/com/sun/hotspot/igv/graph/Figure.java index d85e102f874..f212d1e8b1d 100644 --- a/src/utils/IdealGraphVisualizer/Graph/src/main/java/com/sun/hotspot/igv/graph/Figure.java +++ b/src/utils/IdealGraphVisualizer/Graph/src/main/java/com/sun/hotspot/igv/graph/Figure.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -371,7 +371,7 @@ public class Figure extends Properties.Entity implements Vertex { // search is done on the node label (without line breaks). See also // class NodeQuickSearch in the View module. String label = inputNode.getProperties().resolveString(diagram.getNodeText()); - inputNode.getProperties().setProperty("label", label.replaceAll("\\R", " ")); + inputNode.getProperties().setProperty(InputNode.LABEL_PROPERTY, label.replaceAll("\\R", " ")); // Update figure dimensions, as these are affected by the node text. updateWidth(); diff --git a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/NodeQuickSearch.java b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/NodeQuickSearch.java index 254b8ca15ef..95d6e12d3c4 100644 --- a/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/NodeQuickSearch.java +++ b/src/utils/IdealGraphVisualizer/View/src/main/java/com/sun/hotspot/igv/view/NodeQuickSearch.java @@ -48,8 +48,6 @@ import org.openide.NotifyDescriptor.Message; */ public class NodeQuickSearch implements SearchProvider { - private static final String DEFAULT_PROPERTY = "label"; - /** * Method is called by infrastructure when search operation was requested. * Implementors should evaluate given request and fill response object with @@ -72,7 +70,7 @@ public class NodeQuickSearch implements SearchProvider { String value; if (parts.length == 1) { - name = DEFAULT_PROPERTY; + name = InputNode.LABEL_PROPERTY; rawValue = parts[0]; value = ".*" + Pattern.quote(rawValue) + ".*"; } else { From c54dcefbfd2eb44a569767740dc053813c4f6fe1 Mon Sep 17 00:00:00 2001 From: Francesco Andreuzzi Date: Wed, 1 Oct 2025 14:59:14 +0000 Subject: [PATCH 0024/1639] 8368938: Remove ObjectWaiter::badObjectWaiterPtr Reviewed-by: shade, ayang --- src/hotspot/share/runtime/objectMonitor.hpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/hotspot/share/runtime/objectMonitor.hpp b/src/hotspot/share/runtime/objectMonitor.hpp index 3c925928be2..50aec549045 100644 --- a/src/hotspot/share/runtime/objectMonitor.hpp +++ b/src/hotspot/share/runtime/objectMonitor.hpp @@ -32,6 +32,7 @@ #include "oops/weakHandle.hpp" #include "runtime/javaThread.hpp" #include "utilities/checkedCast.hpp" +#include "utilities/globalDefinitions.hpp" class ObjectMonitor; class ObjectMonitorContentionMark; @@ -72,20 +73,19 @@ class ObjectWaiter : public CHeapObj { void wait_reenter_begin(ObjectMonitor *mon); void wait_reenter_end(ObjectMonitor *mon); - ObjectWaiter* const badObjectWaiterPtr = (ObjectWaiter*) 0xBAD; void set_bad_pointers() { #ifdef ASSERT - this->_prev = badObjectWaiterPtr; - this->_next = badObjectWaiterPtr; + this->_prev = (ObjectWaiter*) badAddressVal; + this->_next = (ObjectWaiter*) badAddressVal; this->TState = ObjectWaiter::TS_RUN; #endif } ObjectWaiter* next() { - assert (_next != badObjectWaiterPtr, "corrupted list!"); + assert (_next != (ObjectWaiter*) badAddressVal, "corrupted list!"); return _next; } ObjectWaiter* prev() { - assert (_prev != badObjectWaiterPtr, "corrupted list!"); + assert (_prev != (ObjectWaiter*) badAddressVal, "corrupted list!"); return _prev; } }; From e44ef0c32b3c2fcd0a6293838d9185b6d0719219 Mon Sep 17 00:00:00 2001 From: Pavel Rappo Date: Wed, 1 Oct 2025 16:05:31 +0000 Subject: [PATCH 0025/1639] 8367704: Fix minor documentation issues in java.time.** Reviewed-by: naoto, rriggs --- .../share/classes/java/time/Duration.java | 30 +++++++++---------- .../share/classes/java/time/Instant.java | 12 ++++---- .../share/classes/java/time/Period.java | 2 +- .../share/classes/java/time/ZoneOffset.java | 6 ++-- .../classes/java/time/ZonedDateTime.java | 8 ++--- .../share/classes/java/time/package-info.java | 8 ++--- .../java/time/temporal/ChronoField.java | 4 +-- .../java/time/temporal/ValueRange.java | 2 +- 8 files changed, 36 insertions(+), 36 deletions(-) diff --git a/src/java.base/share/classes/java/time/Duration.java b/src/java.base/share/classes/java/time/Duration.java index 88d49fa9e45..23577a8a634 100644 --- a/src/java.base/share/classes/java/time/Duration.java +++ b/src/java.base/share/classes/java/time/Duration.java @@ -172,7 +172,7 @@ public final class Duration * Obtains a {@code Duration} representing a number of standard 24 hour days. *

* The seconds are calculated based on the standard definition of a day, - * where each day is 86400 seconds which implies a 24 hour day. + * where each day is 86,400 seconds which implies a 24 hour day. * The nanosecond in second field is set to zero. * * @param days the number of days, positive or negative @@ -187,7 +187,7 @@ public final class Duration * Obtains a {@code Duration} representing a number of standard hours. *

* The seconds are calculated based on the standard definition of an hour, - * where each hour is 3600 seconds. + * where each hour is 3,600 seconds. * The nanosecond in second field is set to zero. * * @param hours the number of hours, positive or negative @@ -375,8 +375,8 @@ public final class Duration *

      *    "PT20.345S" -- parses as "20.345 seconds"
      *    "PT15M"     -- parses as "15 minutes" (where a minute is 60 seconds)
-     *    "PT10H"     -- parses as "10 hours" (where an hour is 3600 seconds)
-     *    "P2D"       -- parses as "2 days" (where a day is 24 hours or 86400 seconds)
+     *    "PT10H"     -- parses as "10 hours" (where an hour is 3,600 seconds)
+     *    "P2D"       -- parses as "2 days" (where a day is 24 hours or 86,400 seconds)
      *    "P2DT3H4M"  -- parses as "2 days, 3 hours and 4 minutes"
      *    "PT-6H3M"    -- parses as "-6 hours and +3 minutes"
      *    "-PT6H3M"    -- parses as "-6 hours and -3 minutes"
@@ -477,7 +477,7 @@ public final class Duration
      * {@link ChronoField#NANO_OF_SECOND NANO_OF_SECOND} field should be supported.
      * 

* The result of this method can be a negative duration if the end is before the start. - * To guarantee to obtain a positive duration call {@link #abs()} on the result. + * To guarantee a positive duration, call {@link #abs()} on the result. * * @param startInclusive the start instant, inclusive, not null * @param endExclusive the end instant, exclusive, not null @@ -752,7 +752,7 @@ public final class Duration /** * Returns a copy of this duration with the specified duration in standard 24 hour days added. *

- * The number of days is multiplied by 86400 to obtain the number of seconds to add. + * The number of days is multiplied by 86,400 to obtain the number of seconds to add. * This is based on the standard definition of a day as 24 hours. *

* This instance is immutable and unaffected by this method call. @@ -893,7 +893,7 @@ public final class Duration /** * Returns a copy of this duration with the specified duration in standard 24 hour days subtracted. *

- * The number of days is multiplied by 86400 to obtain the number of seconds to subtract. + * The number of days is multiplied by 86,400 to obtain the number of seconds to subtract. * This is based on the standard definition of a day as 24 hours. *

* This instance is immutable and unaffected by this method call. @@ -909,7 +909,7 @@ public final class Duration /** * Returns a copy of this duration with the specified duration in hours subtracted. *

- * The number of hours is multiplied by 3600 to obtain the number of seconds to subtract. + * The number of hours is multiplied by 3,600 to obtain the number of seconds to subtract. *

* This instance is immutable and unaffected by this method call. * @@ -924,7 +924,7 @@ public final class Duration /** * Returns a copy of this duration with the specified duration in minutes subtracted. *

- * The number of hours is multiplied by 60 to obtain the number of seconds to subtract. + * The number of minutes is multiplied by 60 to obtain the number of seconds to subtract. *

* This instance is immutable and unaffected by this method call. * @@ -1165,7 +1165,7 @@ public final class Duration * Gets the number of days in this duration. *

* This returns the total number of days in the duration by dividing the - * number of seconds by 86400. + * number of seconds by 86,400. * This is based on the standard definition of a day as 24 hours. *

* This instance is immutable and unaffected by this method call. @@ -1180,7 +1180,7 @@ public final class Duration * Gets the number of hours in this duration. *

* This returns the total number of hours in the duration by dividing the - * number of seconds by 3600. + * number of seconds by 3,600. *

* This instance is immutable and unaffected by this method call. * @@ -1272,7 +1272,7 @@ public final class Duration * Extracts the number of days in the duration. *

* This returns the total number of days in the duration by dividing the - * number of seconds by 86400. + * number of seconds by 86,400. * This is based on the standard definition of a day as 24 hours. *

* This instance is immutable and unaffected by this method call. @@ -1476,10 +1476,10 @@ public final class Duration *

* Examples: *

-     *    "20.345 seconds"                 -- "PT20.345S
+     *    "20.345 seconds"                 -- "PT20.345S"
      *    "15 minutes" (15 * 60 seconds)   -- "PT15M"
-     *    "10 hours" (10 * 3600 seconds)   -- "PT10H"
-     *    "2 days" (2 * 86400 seconds)     -- "PT48H"
+     *    "10 hours" (10 * 3,600 seconds)  -- "PT10H"
+     *    "2 days" (2 * 86,400 seconds)    -- "PT48H"
      * 
* Note that multiples of 24 hours are not output as days to avoid confusion * with {@code Period}. diff --git a/src/java.base/share/classes/java/time/Instant.java b/src/java.base/share/classes/java/time/Instant.java index 1c7a41d7f0e..db8db4aaa38 100644 --- a/src/java.base/share/classes/java/time/Instant.java +++ b/src/java.base/share/classes/java/time/Instant.java @@ -114,15 +114,15 @@ import java.util.Objects; *

* The length of the solar day is the standard way that humans measure time. * This has traditionally been subdivided into 24 hours of 60 minutes of 60 seconds, - * forming a 86400 second day. + * forming an 86,400 second day. *

* Modern timekeeping is based on atomic clocks which precisely define an SI second * relative to the transitions of a Caesium atom. The length of an SI second was defined - * to be very close to the 86400th fraction of a day. + * to be very close to the 86,400th fraction of a day. *

* Unfortunately, as the Earth rotates the length of the day varies. * In addition, over time the average length of the day is getting longer as the Earth slows. - * As a result, the length of a solar day in 2012 is slightly longer than 86400 SI seconds. + * As a result, the length of a solar day in 2012 is slightly longer than 86,400 SI seconds. * The actual length of any given day and the amount by which the Earth is slowing * are not predictable and can only be determined by measurement. * The UT1 time-scale captures the accurate length of day, but is only available some @@ -131,7 +131,7 @@ import java.util.Objects; * The UTC time-scale is a standard approach to bundle up all the additional fractions * of a second from UT1 into whole seconds, known as leap-seconds. * A leap-second may be added or removed depending on the Earth's rotational changes. - * As such, UTC permits a day to have 86399 SI seconds or 86401 SI seconds where + * As such, UTC permits a day to have 86,399 SI seconds or 86,401 SI seconds where * necessary in order to keep the day aligned with the Sun. *

* The modern UTC time-scale was introduced in 1972, introducing the concept of whole leap-seconds. @@ -143,7 +143,7 @@ import java.util.Objects; * Given the complexity of accurate timekeeping described above, this Java API defines * its own time-scale, the Java Time-Scale. *

- * The Java Time-Scale divides each calendar day into exactly 86400 + * The Java Time-Scale divides each calendar day into exactly 86,400 * subdivisions, known as seconds. These seconds may differ from the * SI second. It closely matches the de facto international civil time * scale, the definition of which changes from time to time. @@ -171,7 +171,7 @@ import java.util.Objects; * This is identical to UTC on days that do not have a leap second. * On days that do have a leap second, the leap second is spread equally * over the last 1000 seconds of the day, maintaining the appearance of - * exactly 86400 seconds per day. + * exactly 86,400 seconds per day. *

* For the segment prior to 1972-11-03, extending back arbitrarily far, * the consensus international time scale is defined to be UT1, applied diff --git a/src/java.base/share/classes/java/time/Period.java b/src/java.base/share/classes/java/time/Period.java index 5ee80710edb..745714788c3 100644 --- a/src/java.base/share/classes/java/time/Period.java +++ b/src/java.base/share/classes/java/time/Period.java @@ -765,7 +765,7 @@ public final class Period *

* This instance is immutable and unaffected by this method call. * - * @param daysToSubtract the months to subtract, positive or negative + * @param daysToSubtract the days to subtract, positive or negative * @return a {@code Period} based on this period with the specified days subtracted, not null * @throws ArithmeticException if numeric overflow occurs */ diff --git a/src/java.base/share/classes/java/time/ZoneOffset.java b/src/java.base/share/classes/java/time/ZoneOffset.java index d93c6e2d46d..4199d17735c 100644 --- a/src/java.base/share/classes/java/time/ZoneOffset.java +++ b/src/java.base/share/classes/java/time/ZoneOffset.java @@ -417,9 +417,9 @@ public final class ZoneOffset /** * Obtains an instance of {@code ZoneOffset} specifying the total offset in seconds *

- * The offset must be in the range {@code -18:00} to {@code +18:00}, which corresponds to -64800 to +64800. + * The offset must be in the range {@code -18:00} to {@code +18:00}, which corresponds to -64,800 to +64,800. * - * @param totalSeconds the total time-zone offset in seconds, from -64800 to +64800 + * @param totalSeconds the total time-zone offset in seconds, from -64,800 to +64,800 * @return the ZoneOffset, not null * @throws DateTimeException if the offset is not in the required range */ @@ -450,7 +450,7 @@ public final class ZoneOffset /** * Constructor. * - * @param totalSeconds the total time-zone offset in seconds, from -64800 to +64800 + * @param totalSeconds the total time-zone offset in seconds, from -64,800 to +64,800 */ private ZoneOffset(int totalSeconds) { this.totalSeconds = totalSeconds; diff --git a/src/java.base/share/classes/java/time/ZonedDateTime.java b/src/java.base/share/classes/java/time/ZonedDateTime.java index 962469b3225..57dc98d5c68 100644 --- a/src/java.base/share/classes/java/time/ZonedDateTime.java +++ b/src/java.base/share/classes/java/time/ZonedDateTime.java @@ -136,7 +136,7 @@ import jdk.internal.util.DateTimeHelper; * For Overlaps, the general strategy is that if the local date-time falls in the * middle of an Overlap, then the previous offset will be retained. If there is no * previous offset, or the previous offset is invalid, then the earlier offset is - * used, typically "summer" time.. Two additional methods, + * used, typically "summer" time. Two additional methods, * {@link #withEarlierOffsetAtOverlap()} and {@link #withLaterOffsetAtOverlap()}, * help manage the case of an overlap. *

@@ -246,7 +246,7 @@ public final class ZonedDateTime * Time-zone rules, such as daylight savings, mean that not every local date-time * is valid for the specified zone, thus the local date-time may be adjusted. *

- * The local date time and first combined to form a local date-time. + * The local date and time are first combined to form a local date-time. * The local date-time is then resolved to a single instant on the time-line. * This is achieved by finding a valid offset from UTC/Greenwich for the local * date-time as defined by the {@link ZoneRules rules} of the zone ID. @@ -263,7 +263,7 @@ public final class ZonedDateTime * @param date the local date, not null * @param time the local time, not null * @param zone the time-zone, not null - * @return the offset date-time, not null + * @return the zoned date-time, not null */ public static ZonedDateTime of(LocalDate date, LocalTime time, ZoneId zone) { return of(LocalDateTime.of(date, time), zone); @@ -333,7 +333,7 @@ public final class ZonedDateTime * @param second the second-of-minute to represent, from 0 to 59 * @param nanoOfSecond the nano-of-second to represent, from 0 to 999,999,999 * @param zone the time-zone, not null - * @return the offset date-time, not null + * @return the zoned date-time, not null * @throws DateTimeException if the value of any field is out of range, or * if the day-of-month is invalid for the month-year */ diff --git a/src/java.base/share/classes/java/time/package-info.java b/src/java.base/share/classes/java/time/package-info.java index 8a4fbe44d8b..d0fb7a6c2bc 100644 --- a/src/java.base/share/classes/java/time/package-info.java +++ b/src/java.base/share/classes/java/time/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,7 +65,7 @@ * The main API for dates, times, instants, and durations. *

*

- * The classes defined here represent the principle date-time concepts, + * The classes defined here represent the principal date-time concepts, * including instants, durations, dates, times, time-zones and periods. * They are based on the ISO calendar system, which is the de facto world * calendar following the proleptic Gregorian rules. @@ -150,7 +150,7 @@ *

*

* {@link java.time.OffsetTime} stores a time and offset from UTC without a date. - * This stores a date like '11:30+01:00'. + * This stores a time like '11:30+01:00'. * The {@link java.time.ZoneOffset ZoneOffset} is of the form '+01:00'. *

*

@@ -249,7 +249,7 @@ *

* Multiple calendar systems is an awkward addition to the design challenges. * The first principle is that most users want the standard ISO calendar system. - * As such, the main classes are ISO-only. The second principle is that most of those that want a + * As such, the main classes are ISO-only. The second principle is that most of those who want a * non-ISO calendar system want it for user interaction, thus it is a UI localization issue. * As such, date and time objects should be held as ISO objects in the data model and persistent * storage, only being converted to and from a local calendar for display. diff --git a/src/java.base/share/classes/java/time/temporal/ChronoField.java b/src/java.base/share/classes/java/time/temporal/ChronoField.java index 9e5de367b0e..506737ff268 100644 --- a/src/java.base/share/classes/java/time/temporal/ChronoField.java +++ b/src/java.base/share/classes/java/time/temporal/ChronoField.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -599,7 +599,7 @@ public enum ChronoField implements TemporalField { * A {@link ZoneOffset} represents the period of time that local time differs from UTC/Greenwich. * This is usually a fixed number of hours and minutes. * It is equivalent to the {@link ZoneOffset#getTotalSeconds() total amount} of the offset in seconds. - * For example, during the winter Paris has an offset of {@code +01:00}, which is 3600 seconds. + * For example, during the winter, Paris has an offset of {@code +01:00}, which is 3,600 seconds. *

* This field is strictly defined to have the same meaning in all calendar systems. * This is necessary to ensure interoperation between calendars. diff --git a/src/java.base/share/classes/java/time/temporal/ValueRange.java b/src/java.base/share/classes/java/time/temporal/ValueRange.java index 442cf0a2509..27e71e77d66 100644 --- a/src/java.base/share/classes/java/time/temporal/ValueRange.java +++ b/src/java.base/share/classes/java/time/temporal/ValueRange.java @@ -78,7 +78,7 @@ import java.time.DateTimeException; * Only the minimum and maximum values are provided. * It is possible for there to be invalid values within the outer range. * For example, a weird field may have valid values of 1, 2, 4, 6, 7, thus - * have a range of '1 - 7', despite that fact that values 3 and 5 are invalid. + * have a range of '1 - 7', despite the fact that values 3 and 5 are invalid. *

* Instances of this class are not tied to a specific field. * From 6b72b778039afce0e25986114d15dd29a6786529 Mon Sep 17 00:00:00 2001 From: Justin Lu Date: Wed, 1 Oct 2025 17:57:43 +0000 Subject: [PATCH 0026/1639] 6177299: [Fmt-Nu] NumberFormat.getPercentInstance() does not work correctly Reviewed-by: naoto --- .../classes/java/text/DecimalFormat.java | 7 ++-- .../Format/NumberFormat/NumberRegression.java | 41 ++++++++++++++++++- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/java.base/share/classes/java/text/DecimalFormat.java b/src/java.base/share/classes/java/text/DecimalFormat.java index 7ace5e136fe..c803a97ad86 100644 --- a/src/java.base/share/classes/java/text/DecimalFormat.java +++ b/src/java.base/share/classes/java/text/DecimalFormat.java @@ -2335,9 +2335,10 @@ public class DecimalFormat extends NumberFormat { // (bug 4162852). if (multiplier != 1 && gotDouble) { longResult = (long)doubleResult; - gotDouble = ((doubleResult != (double)longResult) || - (doubleResult == 0.0 && 1/doubleResult < 0.0)) && - !isParseIntegerOnly(); + gotDouble = ((doubleResult >= Long.MAX_VALUE || doubleResult <= Long.MIN_VALUE) || + (doubleResult != (double)longResult) || + (doubleResult == 0.0 && 1/doubleResult < 0.0)) && + !isParseIntegerOnly(); } // cast inside of ?: because of binary numeric promotion, JLS 15.25 diff --git a/test/jdk/java/text/Format/NumberFormat/NumberRegression.java b/test/jdk/java/text/Format/NumberFormat/NumberRegression.java index dcc87643b2b..1b3452012cd 100644 --- a/test/jdk/java/text/Format/NumberFormat/NumberRegression.java +++ b/test/jdk/java/text/Format/NumberFormat/NumberRegression.java @@ -29,7 +29,8 @@ * 4098741 4099404 4101481 4106658 4106662 4106664 4108738 4110936 4122840 * 4125885 4134034 4134300 4140009 4141750 4145457 4147295 4147706 4162198 * 4162852 4167494 4170798 4176114 4179818 4212072 4212073 4216742 4217661 - * 4243011 4243108 4330377 4233840 4241880 4833877 8008577 8227313 8174269 + * 4243011 4243108 4330377 4233840 4241880 4833877 6177299 8008577 8227313 + * 8174269 * @summary Regression tests for NumberFormat and associated classes * @library /java/text/testlib * @build HexDumpReader TestUtils @@ -56,10 +57,13 @@ import java.util.*; import java.math.BigDecimal; import java.io.*; import java.math.BigInteger; + import sun.util.resources.LocaleData; import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.fail; public class NumberRegression { @@ -1847,6 +1851,41 @@ public class NumberRegression { ", got: " + parsed); } } + + /** + * 6177299: DecimalFormat w/ multiplier applied may incorrectly return + * a Double as Long.MAX_VALUE. + */ + @Test + void largePosParseTest() { + var df = NumberFormat.getPercentInstance(Locale.ENGLISH); // Default w/ multiplier 100 + // Parsed string after multiplier applied is beyond long range + assertEquals(9.223372036854777E18, + assertDoesNotThrow(() -> df.parse("922,337,203,685,477,700,000%"))); + // Fails before 6177299 fix and returns as long + assertEquals(9.223372036854776E18, + assertDoesNotThrow(() -> df.parse("922,337,203,685,477,600,000%"))); + // Within long range -> Expect to get longs as long as ulp >= 1 + assertEquals((long) 9.223372036854775E18, + assertDoesNotThrow(() -> df.parse("922,337,203,685,477,500,000%"))); + } + + /** + * 6177299: Negative version of above test. + */ + @Test + void largeNegParseTest() { + var df = NumberFormat.getPercentInstance(Locale.ENGLISH); // Default w/ multiplier 100 + // Parsed string after multiplier applied is beyond long range + assertEquals(-9.223372036854777E18, + assertDoesNotThrow(() -> df.parse("-922,337,203,685,477,700,000%"))); + // Fails before 6177299 fix and returns as long + assertEquals(-9.223372036854776E18, + assertDoesNotThrow(() -> df.parse("-922,337,203,685,477,600,000%"))); + // Within long range -> Expect to get longs as long as ulp >= 1 + assertEquals((long) -9.223372036854775E18, + assertDoesNotThrow(() -> df.parse("-922,337,203,685,477,500,000%"))); + } } @SuppressWarnings("serial") From ef724f40c1f3cdddd215d50edf512bb06825085d Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Wed, 1 Oct 2025 19:56:05 +0000 Subject: [PATCH 0027/1639] 8368985: Small Float16 refactorings Reviewed-by: rgiulietti, jbhateja --- .../classes/jdk/incubator/vector/Float16.java | 25 +++++++++++-------- .../vector/BasicFloat16ArithTests.java | 10 +++----- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16.java index 2173c741e38..b75adf350b6 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16.java @@ -146,6 +146,10 @@ public final class Float16 */ public static final Float16 NaN = valueOf(Float.NaN); + private static final Float16 ZERO = valueOf(0); + + private static final Float16 ONE = valueOf(1); + /** * A constant holding the largest positive finite value of type * {@code Float16}, @@ -612,7 +616,7 @@ public final class Float16 * Float16}. */ private static final Float16[] FLOAT16_10_POW = { - Float16.valueOf(1), Float16.valueOf(10), Float16.valueOf(100), + Float16.ONE, Float16.valueOf(10), Float16.valueOf(100), Float16.valueOf(1_000), Float16.valueOf(10_000) }; @@ -649,14 +653,14 @@ public final class Float16 private static Float16 fullFloat16Value(BigDecimal bd) { if (BigDecimal.ZERO.compareTo(bd) == 0) { - return Float16.valueOf(0); + return ZERO; } BigInteger w = bd.unscaledValue().abs(); int scale = bd.scale(); long qb = w.bitLength() - (long) Math.ceil(scale * L); Float16 signum = Float16.valueOf(bd.signum()); if (qb < Q_MIN_F16 - 2) { // qb < -26 - return Float16.multiply(signum, Float16.valueOf(0)); + return Float16.multiply(signum, ZERO); } if (qb > Q_MAX_F16 + P_F16 + 1) { // qb > 17 return Float16.multiply(signum, Float16.POSITIVE_INFINITY); @@ -729,7 +733,7 @@ public final class Float16 public static boolean isNaN(Float16 f16) { final short bits = float16ToRawShortBits(f16); // A NaN value has all ones in its exponent and a non-zero significand - return ((bits & 0x7c00) == 0x7c00 && (bits & 0x03ff) != 0); + return ((bits & EXP_BIT_MASK) == EXP_BIT_MASK && (bits & SIGNIF_BIT_MASK) != 0); } /** @@ -748,8 +752,9 @@ public final class Float16 * @see Double#isInfinite(double) */ public static boolean isInfinite(Float16 f16) { - return ((float16ToRawShortBits(f16) ^ - float16ToRawShortBits(POSITIVE_INFINITY)) & 0x7fff) == 0; + final short bits = float16ToRawShortBits(f16); + // An infinite value has all ones in its exponent and a zero significand + return ((bits & EXP_BIT_MASK) == EXP_BIT_MASK && (bits & SIGNIF_BIT_MASK) == 0); } /** @@ -769,7 +774,7 @@ public final class Float16 * @see Double#isFinite(double) */ public static boolean isFinite(Float16 f16) { - return (float16ToRawShortBits(f16) & (short)0x0000_7FFF) <= + return (float16ToRawShortBits(f16) & (EXP_BIT_MASK | SIGNIF_BIT_MASK)) <= float16ToRawShortBits(MAX_VALUE); } @@ -1563,7 +1568,7 @@ public final class Float16 assert exp <= MAX_EXPONENT && exp >= MIN_EXPONENT; // ulp(x) is usually 2^(SIGNIFICAND_WIDTH-1)*(2^ilogb(x)) // Let float -> float16 conversion handle encoding issues. - yield scalb(valueOf(1), exp - (PRECISION - 1)); + yield scalb(ONE, exp - (PRECISION - 1)); } }; } @@ -1685,7 +1690,7 @@ public final class Float16 Float16Consts.SIGNIFICAND_WIDTH + 1; // Make sure scaling factor is in a reasonable range - scaleFactor = Math.max(Math.min(scaleFactor, MAX_SCALE), -MAX_SCALE); + scaleFactor = Math.clamp(scaleFactor, -MAX_SCALE, MAX_SCALE); int DoubleConsts_EXP_BIAS = 1023; /* @@ -1743,7 +1748,7 @@ public final class Float16 * @see Math#signum(double) */ public static Float16 signum(Float16 f) { - return (f.floatValue() == 0.0f || isNaN(f)) ? f : copySign(valueOf(1), f); + return (f.floatValue() == 0.0f || isNaN(f)) ? f : copySign(ONE, f); } // TODO: Temporary location for this functionality while Float16 diff --git a/test/jdk/jdk/incubator/vector/BasicFloat16ArithTests.java b/test/jdk/jdk/incubator/vector/BasicFloat16ArithTests.java index 0c08099031a..755745394fc 100644 --- a/test/jdk/jdk/incubator/vector/BasicFloat16ArithTests.java +++ b/test/jdk/jdk/incubator/vector/BasicFloat16ArithTests.java @@ -408,11 +408,10 @@ public class BasicFloat16ArithTests { for(var testCase : testCases) { float arg = testCase[0]; float expected = testCase[1]; - // Exponents are in-range for Float16 - Float16 result = valueOfExact(getExponent(valueOfExact(arg))); + float result = (float)getExponent(valueOfExact(arg)); - if (Float.compare(expected, result.floatValue()) != 0) { - checkFloat16(result, expected, "getExponent(" + arg + ")"); + if (Float.compare(expected, result) != 0) { + checkFloat16(Float16.valueOf(result), expected, "getExponent(" + arg + ")"); } } return; @@ -444,8 +443,7 @@ public class BasicFloat16ArithTests { for(var testCase : testCases) { float arg = testCase[0]; float expected = testCase[1]; - // Exponents are in-range for Float16 - Float16 result = ulp(valueOfExact(arg)); + Float16 result = ulp(valueOfExact(arg)); if (Float.compare(expected, result.floatValue()) != 0) { checkFloat16(result, expected, "ulp(" + arg + ")"); From db6320df980ebe7cf2a1c727970cc937ab549b97 Mon Sep 17 00:00:00 2001 From: Johannes Graham Date: Wed, 1 Oct 2025 20:00:43 +0000 Subject: [PATCH 0028/1639] 8368968: FloatingDecimal: Clean up unused code Reviewed-by: rgiulietti --- .../jdk/internal/math/FloatingDecimal.java | 162 +----------------- 1 file changed, 2 insertions(+), 160 deletions(-) diff --git a/src/java.base/share/classes/jdk/internal/math/FloatingDecimal.java b/src/java.base/share/classes/jdk/internal/math/FloatingDecimal.java index e4354b9b958..e90ca4d75f1 100644 --- a/src/java.base/share/classes/jdk/internal/math/FloatingDecimal.java +++ b/src/java.base/share/classes/jdk/internal/math/FloatingDecimal.java @@ -27,8 +27,6 @@ package jdk.internal.math; import jdk.internal.vm.annotation.Stable; -import java.util.Arrays; - /** * A class for converting between ASCII and decimal representations of a single * or double precision floating point number. Most conversions are provided via @@ -102,7 +100,6 @@ public class FloatingDecimal{ * values into an ASCII String representation. */ public interface BinaryToASCIIConverter { - int getChars(byte[] result); /** * Retrieves the decimal exponent most closely corresponding to this value. @@ -117,20 +114,6 @@ public class FloatingDecimal{ */ int getDigits(byte[] digits); - /** - * Indicates the sign of the value. - * @return {@code value < 0.0}. - */ - boolean isNegative(); - - /** - * Indicates whether the value is either infinite or not a number. - * - * @return true if and only if the value is NaN - * or infinite. - */ - boolean isExceptional(); - /** * Indicates whether the value was rounded up during the binary to ASCII * conversion. @@ -147,63 +130,9 @@ public class FloatingDecimal{ boolean decimalDigitsExact(); } - /** - * A BinaryToASCIIConverter which represents NaN - * and infinite values. - */ - private static class ExceptionalBinaryToASCIIBuffer implements BinaryToASCIIConverter { - private final String image; - private final boolean isNegative; - - public ExceptionalBinaryToASCIIBuffer(String image, boolean isNegative) { - this.image = image; - this.isNegative = isNegative; - } - - @Override - @SuppressWarnings("deprecation") - public int getChars(byte[] chars) { - image.getBytes(0, image.length(), chars, 0); - return image.length(); - } - - @Override - public int getDecimalExponent() { - throw new IllegalArgumentException("Exceptional value does not have an exponent"); - } - - @Override - public int getDigits(byte[] digits) { - throw new IllegalArgumentException("Exceptional value does not have digits"); - } - - @Override - public boolean isNegative() { - return isNegative; - } - - @Override - public boolean isExceptional() { - return true; - } - - @Override - public boolean digitsRoundedUp() { - throw new IllegalArgumentException("Exceptional value is not rounded"); - } - - @Override - public boolean decimalDigitsExact() { - throw new IllegalArgumentException("Exceptional value is not exact"); - } - } - private static final String INFINITY_REP = "Infinity"; private static final String NAN_REP = "NaN"; - private static final BinaryToASCIIConverter B2AC_POSITIVE_INFINITY = new ExceptionalBinaryToASCIIBuffer(INFINITY_REP, false); - private static final BinaryToASCIIConverter B2AC_NEGATIVE_INFINITY = new ExceptionalBinaryToASCIIBuffer("-" + INFINITY_REP, true); - private static final BinaryToASCIIConverter B2AC_NOT_A_NUMBER = new ExceptionalBinaryToASCIIBuffer(NAN_REP, false); private static final BinaryToASCIIConverter B2AC_POSITIVE_ZERO = new BinaryToASCIIBuffer(false, new byte[]{'0'}); private static final BinaryToASCIIConverter B2AC_NEGATIVE_ZERO = new BinaryToASCIIBuffer(true, new byte[]{'0'}); @@ -260,16 +189,6 @@ public class FloatingDecimal{ return this.nDigits; } - @Override - public boolean isNegative() { - return isNegative; - } - - @Override - public boolean isExceptional() { - return false; - } - @Override public boolean digitsRoundedUp() { return decimalDigitsRoundedUp; @@ -826,83 +745,6 @@ public class FloatingDecimal{ 61, }; - /** - * Converts the decimal representation of a floating-point number into its - * ASCII character representation and stores it in the provided byte array. - * - * @param result the byte array to store the ASCII representation, must have length at least 26 - * @return the number of characters written to the result array - */ - public int getChars(byte[] result) { - assert nDigits <= 19 : nDigits; // generous bound on size of nDigits - int i = 0; - if (isNegative) { - result[0] = '-'; - i = 1; - } - if (decExponent > 0 && decExponent < 8) { - // print digits.digits. - int charLength = Math.min(nDigits, decExponent); - System.arraycopy(digits, firstDigitIndex, result, i, charLength); - i += charLength; - if (charLength < decExponent) { - charLength = decExponent - charLength; - Arrays.fill(result, i, i + charLength, (byte) '0'); - i += charLength; - result[i++] = '.'; - result[i++] = '0'; - } else { - result[i++] = '.'; - if (charLength < nDigits) { - int t = nDigits - charLength; - System.arraycopy(digits, firstDigitIndex + charLength, result, i, t); - i += t; - } else { - result[i++] = '0'; - } - } - } else if (decExponent <= 0 && decExponent > -3) { - result[i++] = '0'; - result[i++] = '.'; - if (decExponent != 0) { - Arrays.fill(result, i, i-decExponent, (byte) '0'); - i -= decExponent; - } - System.arraycopy(digits, firstDigitIndex, result, i, nDigits); - i += nDigits; - } else { - result[i++] = digits[firstDigitIndex]; - result[i++] = '.'; - if (nDigits > 1) { - System.arraycopy(digits, firstDigitIndex+1, result, i, nDigits - 1); - i += nDigits - 1; - } else { - result[i++] = '0'; - } - result[i++] = 'E'; - int e; - if (decExponent <= 0) { - result[i++] = '-'; - e = -decExponent + 1; - } else { - e = decExponent - 1; - } - // decExponent has 1, 2, or 3, digits - if (e <= 9) { - result[i++] = (byte) (e + '0'); - } else if (e <= 99) { - result[i++] = (byte) (e / 10 + '0'); - result[i++] = (byte) (e % 10 + '0'); - } else { - result[i++] = (byte) (e / 100 + '0'); - e %= 100; - result[i++] = (byte) (e / 10 + '0'); - result[i++] = (byte) (e % 10 + '0'); - } - } - return i; - } - } private static final ThreadLocal threadLocalBinaryToASCIIBuffer = @@ -1707,9 +1549,9 @@ public class FloatingDecimal{ // Discover obvious special cases of NaN and Infinity. if ( binExp == (int)(DoubleConsts.EXP_BIT_MASK>>EXP_SHIFT) ) { if ( fractBits == 0L ){ - return isNegative ? B2AC_NEGATIVE_INFINITY : B2AC_POSITIVE_INFINITY; + throw new IllegalArgumentException((isNegative ? "-" : "") + INFINITY_REP); } else { - return B2AC_NOT_A_NUMBER; + throw new IllegalArgumentException(NAN_REP); } } // Finish unpacking From 4df41d2a751e2942c2188ed01313d78e681835bc Mon Sep 17 00:00:00 2001 From: Igor Veresov Date: Wed, 1 Oct 2025 23:15:13 +0000 Subject: [PATCH 0029/1639] 8368698: runtime/cds/appcds/aotCache/OldClassSupport.java assert(can_add()) failed: Cannot add TrainingData objects Reviewed-by: heidinga, iklam --- src/hotspot/share/oops/trainingData.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/oops/trainingData.cpp b/src/hotspot/share/oops/trainingData.cpp index 41fbc6de994..ca5883a19ca 100644 --- a/src/hotspot/share/oops/trainingData.cpp +++ b/src/hotspot/share/oops/trainingData.cpp @@ -328,7 +328,9 @@ void CompileTrainingData::notice_jit_observation(ciEnv* env, ciBaseObject* what) // This JIT task is (probably) requesting that ik be initialized, // so add him to my _init_deps list. TrainingDataLocker l; - add_init_dep(ktd); + if (l.can_add()) { + add_init_dep(ktd); + } } } } From fa3af820ad310704e8d25cf496f676e09d60797d Mon Sep 17 00:00:00 2001 From: Boris Ulasevich Date: Wed, 1 Oct 2025 23:49:03 +0000 Subject: [PATCH 0030/1639] 8338197: [ubsan] ad_x86.hpp:6417:11: runtime error: shift exponent 100 is too large for 32-bit type 'unsigned int' Reviewed-by: kvn, dlong --- src/hotspot/share/adlc/output_h.cpp | 28 +++++++++++----------------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/src/hotspot/share/adlc/output_h.cpp b/src/hotspot/share/adlc/output_h.cpp index 8a5ad72137a..6cb82f4df7f 100644 --- a/src/hotspot/share/adlc/output_h.cpp +++ b/src/hotspot/share/adlc/output_h.cpp @@ -759,20 +759,15 @@ void ArchDesc::declare_pipe_classes(FILE *fp_hpp) { if (_pipeline->_maxcycleused <= 32) { fprintf(fp_hpp, "protected:\n"); - fprintf(fp_hpp, " %s _mask;\n\n", _pipeline->_maxcycleused <= 32 ? "uint" : "uint64_t" ); + fprintf(fp_hpp, " uint32_t _mask;\n\n"); fprintf(fp_hpp, "public:\n"); fprintf(fp_hpp, " Pipeline_Use_Cycle_Mask() : _mask(0) {}\n\n"); - if (_pipeline->_maxcycleused <= 32) - fprintf(fp_hpp, " Pipeline_Use_Cycle_Mask(uint mask) : _mask(mask) {}\n\n"); - else { - fprintf(fp_hpp, " Pipeline_Use_Cycle_Mask(uint mask1, uint mask2) : _mask((((uint64_t)mask1) << 32) | mask2) {}\n\n"); - fprintf(fp_hpp, " Pipeline_Use_Cycle_Mask(uint64_t mask) : _mask(mask) {}\n\n"); - } + fprintf(fp_hpp, " Pipeline_Use_Cycle_Mask(uint32_t mask) : _mask(mask) {}\n\n"); fprintf(fp_hpp, " bool overlaps(const Pipeline_Use_Cycle_Mask &in2) const {\n"); fprintf(fp_hpp, " return ((_mask & in2._mask) != 0);\n"); fprintf(fp_hpp, " }\n\n"); fprintf(fp_hpp, " Pipeline_Use_Cycle_Mask& operator<<=(int n) {\n"); - fprintf(fp_hpp, " _mask <<= n;\n"); + fprintf(fp_hpp, " _mask <<= (n < 32) ? n : 31;\n"); fprintf(fp_hpp, " return *this;\n"); fprintf(fp_hpp, " }\n\n"); fprintf(fp_hpp, " void Or(const Pipeline_Use_Cycle_Mask &in2) {\n"); @@ -785,7 +780,7 @@ void ArchDesc::declare_pipe_classes(FILE *fp_hpp) { fprintf(fp_hpp, "protected:\n"); uint masklen = (_pipeline->_maxcycleused + 31) >> 5; uint l; - fprintf(fp_hpp, " uint "); + fprintf(fp_hpp, " uint32_t "); for (l = 1; l <= masklen; l++) fprintf(fp_hpp, "_mask%d%s", l, l < masklen ? ", " : ";\n\n"); fprintf(fp_hpp, "public:\n"); @@ -794,7 +789,7 @@ void ArchDesc::declare_pipe_classes(FILE *fp_hpp) { fprintf(fp_hpp, "_mask%d(0)%s", l, l < masklen ? ", " : " {}\n\n"); fprintf(fp_hpp, " Pipeline_Use_Cycle_Mask("); for (l = 1; l <= masklen; l++) - fprintf(fp_hpp, "uint mask%d%s", l, l < masklen ? ", " : ") : "); + fprintf(fp_hpp, "uint32_t mask%d%s", l, l < masklen ? ", " : ") : "); for (l = 1; l <= masklen; l++) fprintf(fp_hpp, "_mask%d(mask%d)%s", l, l, l < masklen ? ", " : " {}\n\n"); @@ -805,10 +800,10 @@ void ArchDesc::declare_pipe_classes(FILE *fp_hpp) { fprintf(fp_hpp, " return out;\n"); fprintf(fp_hpp, " }\n\n"); fprintf(fp_hpp, " bool overlaps(const Pipeline_Use_Cycle_Mask &in2) const {\n"); - fprintf(fp_hpp, " return ("); + fprintf(fp_hpp, " return "); for (l = 1; l <= masklen; l++) fprintf(fp_hpp, "((_mask%d & in2._mask%d) != 0)%s", l, l, l < masklen ? " || " : ""); - fprintf(fp_hpp, ") ? true : false;\n"); + fprintf(fp_hpp, ";\n"); fprintf(fp_hpp, " }\n\n"); fprintf(fp_hpp, " Pipeline_Use_Cycle_Mask& operator<<=(int n) {\n"); fprintf(fp_hpp, " if (n >= 32)\n"); @@ -819,10 +814,10 @@ void ArchDesc::declare_pipe_classes(FILE *fp_hpp) { fprintf(fp_hpp, " } while ((n -= 32) >= 32);\n\n"); fprintf(fp_hpp, " if (n > 0) {\n"); fprintf(fp_hpp, " uint m = 32 - n;\n"); - fprintf(fp_hpp, " uint mask = (1 << n) - 1;\n"); - fprintf(fp_hpp, " uint temp%d = mask & (_mask%d >> m); _mask%d <<= n;\n", 2, 1, 1); + fprintf(fp_hpp, " uint32_t mask = (1 << n) - 1;\n"); + fprintf(fp_hpp, " uint32_t temp%d = mask & (_mask%d >> m); _mask%d <<= n;\n", 2, 1, 1); for (l = 2; l < masklen; l++) { - fprintf(fp_hpp, " uint temp%d = mask & (_mask%d >> m); _mask%d <<= n; _mask%d |= temp%d;\n", l+1, l, l, l, l); + fprintf(fp_hpp, " uint32_t temp%d = mask & (_mask%d >> m); _mask%d <<= n; _mask%d |= temp%d;\n", l+1, l, l, l, l); } fprintf(fp_hpp, " _mask%d <<= n; _mask%d |= temp%d;\n", masklen, masklen, masklen); fprintf(fp_hpp, " }\n"); @@ -872,8 +867,7 @@ void ArchDesc::declare_pipe_classes(FILE *fp_hpp) { fprintf(fp_hpp, " }\n\n"); fprintf(fp_hpp, " void step(uint cycles) {\n"); fprintf(fp_hpp, " _used = 0;\n"); - fprintf(fp_hpp, " uint max_shift = 8 * sizeof(_mask) - 1;\n"); - fprintf(fp_hpp, " _mask <<= (cycles < max_shift) ? cycles : max_shift;\n"); + fprintf(fp_hpp, " _mask <<= cycles;\n"); fprintf(fp_hpp, " }\n\n"); fprintf(fp_hpp, " friend class Pipeline_Use;\n"); fprintf(fp_hpp, "};\n\n"); From 5251405ce9ab1cbd84b798a538cb3865ea4675e9 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Thu, 2 Oct 2025 06:52:59 +0000 Subject: [PATCH 0031/1639] 8368848: JShell's code completion not always working for multi-snippet inputs Reviewed-by: asotona --- .../classes/jdk/jshell/OuterWrapMap.java | 17 ++- .../share/classes/jdk/jshell/SnippetMaps.java | 6 +- .../jdk/jshell/SourceCodeAnalysisImpl.java | 118 +++++++++++++++--- .../jdk/jshell/CompletionSuggestionTest.java | 10 ++ 4 files changed, 125 insertions(+), 26 deletions(-) diff --git a/src/jdk.jshell/share/classes/jdk/jshell/OuterWrapMap.java b/src/jdk.jshell/share/classes/jdk/jshell/OuterWrapMap.java index 6f7f3fe42c3..61fb3bdfc9a 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/OuterWrapMap.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/OuterWrapMap.java @@ -73,7 +73,11 @@ class OuterWrapMap { OuterWrap wrapInClass(Set except, Collection plus, List snippets, List wraps) { - String imports = state.maps.packageAndImportsExcept(except, plus); + List extraImports = + plus.stream() + .map(psi -> psi.importLine(state)) + .toList(); + String imports = state.maps.packageAndImportsExcept(except, extraImports); // className is unique to the set of snippets and their version (seq) String className = REPL_CLASS_PREFIX + snippets.stream() .sorted((sn1, sn2) -> sn1.key().index() - sn2.key().index()) @@ -86,9 +90,16 @@ class OuterWrapMap { } OuterWrap wrapInTrialClass(Wrap wrap) { - String imports = state.maps.packageAndImportsExcept(null, null); + return wrapInTrialClass(List.of(), List.of(), wrap); + } + + OuterWrap wrapInTrialClass(List extraImports, List preWraps, Wrap wrap) { + String imports = state.maps.packageAndImportsExcept(null, extraImports); + List allWraps = new ArrayList<>(); + allWraps.addAll(preWraps); + allWraps.add(wrap); CompoundWrap w = wrappedInClass(REPL_DOESNOTMATTER_CLASS_NAME, imports, - Collections.singletonList(wrap)); + allWraps); return new OuterWrap(w); } diff --git a/src/jdk.jshell/share/classes/jdk/jshell/SnippetMaps.java b/src/jdk.jshell/share/classes/jdk/jshell/SnippetMaps.java index bd0c9d86db3..992d97a7040 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/SnippetMaps.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/SnippetMaps.java @@ -105,7 +105,7 @@ final class SnippetMaps { return new ArrayList<>(snippets); } - String packageAndImportsExcept(Set except, Collection plus) { + String packageAndImportsExcept(Set except, Collection extraImports) { StringBuilder sb = new StringBuilder(); sb.append("package ").append(REPL_PACKAGE).append(";\n"); for (Snippet si : keyIndexToSnippet) { @@ -113,9 +113,7 @@ final class SnippetMaps { sb.append(si.importLine(state)); } } - if (plus != null) { - plus.forEach(psi -> sb.append(psi.importLine(state))); - } + extraImports.forEach(sb::append); return sb.toString(); } diff --git a/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java b/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java index f27441b7262..19bad110a5d 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java @@ -300,17 +300,8 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis { identifier = m.group(); } } - code = code.substring(0, cursor); - if (code.trim().isEmpty()) { //TODO: comment handling - code += ";"; - } - boolean[] moduleImport = new boolean[1]; - OuterWrap codeWrap = switch (guessKind(code, moduleImport)) { - case IMPORT -> moduleImport[0] ? proc.outerMap.wrapImport(Wrap.simpleWrap(code), null) - : proc.outerMap.wrapImport(Wrap.simpleWrap(code + "any.any"), null); - case CLASS, METHOD -> proc.outerMap.wrapInTrialClass(Wrap.classMemberWrap(code)); - default -> proc.outerMap.wrapInTrialClass(Wrap.methodWrap(code)); - }; + + OuterWrap codeWrap = wrapCodeForCompletion(code, cursor, true); String[] requiredPrefix = new String[] {identifier}; return computeSuggestions(codeWrap, code, cursor, requiredPrefix, anchor).stream() .filter(s -> filteringText(s).startsWith(requiredPrefix[0]) && !s.continuation().equals(REPL_DOESNOTMATTER_CLASS_NAME)) @@ -1740,15 +1731,11 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis { }; private List documentationImpl(String code, int cursor, boolean computeJavadoc) { - code = code.substring(0, cursor); - if (code.trim().isEmpty()) { //TODO: comment handling - code += ";"; - } - - if (guessKind(code) == Kind.IMPORT) + OuterWrap codeWrap = wrapCodeForCompletion(code, cursor, false); + if (codeWrap == null) { + //import: return Collections.emptyList(); - - OuterWrap codeWrap = proc.outerMap.wrapInTrialClass(Wrap.methodWrap(code)); + } return proc.taskFactory.analyze(codeWrap, List.of(keepParameterNames), at -> { SourcePositions sp = at.trees().getSourcePositions(); CompilationUnitTree topLevel = at.firstCuTree(); @@ -2434,6 +2421,99 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis { INDEXER.submit(() -> {}).get(); } + private OuterWrap wrapCodeForCompletion(String code, int cursor, boolean wrapImports) { + code = code.substring(0, cursor); + if (code.trim().isEmpty()) { //TODO: comment handling + code += ";"; + } + + List imports = new ArrayList<>(); + List declarationParts = new ArrayList<>(); + String lastImport = null; + boolean lastImportIsModuleImport = false; + Wrap declarationWrap = null; + Wrap pendingWrap = null; + String input = code; + boolean cont = true; + int startOffset = 0; + + while (cont) { + if (lastImport != null) { + imports.add(lastImport); + lastImport = null; + } + if (declarationWrap != null) { + declarationParts.add(declarationWrap); + declarationWrap = null; + pendingWrap = null; + } + + String current; + SourceCodeAnalysis.CompletionInfo completeness = analyzeCompletion(input); + int newStartOffset; + + if (completeness.completeness().isComplete() && !completeness.remaining().isBlank()) { + current = input.substring(0, input.length() - completeness.remaining().length()); + newStartOffset = startOffset + input.length() - completeness.remaining().length(); + input = completeness.remaining(); + cont = true; + } else { + current = input; + cont = false; + newStartOffset = startOffset; + } + + boolean[] moduleImport = new boolean[1]; + + switch (guessKind(current, moduleImport)) { + case IMPORT -> { + lastImport = current; + lastImportIsModuleImport = moduleImport[0]; + } + case CLASS, METHOD -> { + pendingWrap = declarationWrap = Wrap.classMemberWrap(whitespaces(code, startOffset) + current); + } + case VARIABLE -> { + declarationWrap = Wrap.classMemberWrap(whitespaces(code, startOffset) + current); + pendingWrap = Wrap.methodWrap(whitespaces(code, startOffset) + current); + } + default -> { + pendingWrap = declarationWrap = Wrap.methodWrap(whitespaces(code, startOffset) + current); + } + } + + startOffset = newStartOffset; + } + + if (lastImport != null) { + if (wrapImports) { + return proc.outerMap.wrapImport(Wrap.simpleWrap(whitespaces(code, startOffset) + lastImport + (!lastImportIsModuleImport ? "any.any" : "")), null); + } else { + return null; + } + } + + if (pendingWrap != null) { + return proc.outerMap.wrapInTrialClass(imports, declarationParts, pendingWrap); + } + + throw new IllegalStateException("No pending wrap for: " + code); + } + + private static String whitespaces(String input, int offset) { + StringBuilder result = new StringBuilder(); + + for (int i = 0; i < offset; i++) { + if (input.charAt(i) == '\n') { + result.append('\n'); + } else { + result.append(' '); + } + } + + return result.toString(); + } + /** * A candidate for continuation of the given user's input. */ diff --git a/test/langtools/jdk/jshell/CompletionSuggestionTest.java b/test/langtools/jdk/jshell/CompletionSuggestionTest.java index 19f7b89a1b3..7907fa4d027 100644 --- a/test/langtools/jdk/jshell/CompletionSuggestionTest.java +++ b/test/langtools/jdk/jshell/CompletionSuggestionTest.java @@ -941,4 +941,14 @@ public class CompletionSuggestionTest extends KullaTesting { assertEval("import static java.lang.annotation.RetentionPolicy.*;"); assertCompletion("@AnnA(C|", true, "CLASS"); } + + @Test + public void testMultiSnippet() { + assertCompletion("String s = \"\"; s.len|", true, "length()"); + assertCompletion("String s() { return \"\"; } s().len|", true, "length()"); + assertCompletion("String s() { return \"\"; } import java.util.List; List.o|", true, "of("); + assertCompletion("String s() { return \"\"; } import java.ut| ", true, "util."); + assertCompletion("class S { public int length() { return 0; } } new S().len|", true, "length()"); + assertSignature("void f() { } f(|", "void f()"); + } } From dfd383224dbc2e41c9f44b1acd09ffb179cc38f3 Mon Sep 17 00:00:00 2001 From: Francesco Andreuzzi Date: Thu, 2 Oct 2025 08:58:54 +0000 Subject: [PATCH 0032/1639] 8368966: Remove spurious VMStructs friends Reviewed-by: stefank, ayang --- src/hotspot/share/ci/ciObjectFactory.hpp | 1 - src/hotspot/share/classfile/compactHashtable.hpp | 1 - src/hotspot/share/code/codeBlob.hpp | 4 ---- src/hotspot/share/code/dependencyContext.hpp | 2 -- src/hotspot/share/code/nmethod.hpp | 1 - src/hotspot/share/compiler/abstractCompiler.hpp | 2 -- src/hotspot/share/compiler/oopMap.hpp | 1 - src/hotspot/share/gc/epsilon/epsilonBarrierSet.hpp | 2 -- src/hotspot/share/gc/epsilon/epsilonMonitoringSupport.cpp | 2 -- src/hotspot/share/gc/g1/g1Allocator.hpp | 2 -- src/hotspot/share/gc/g1/g1BarrierSet.hpp | 1 - src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp | 4 +--- src/hotspot/share/gc/g1/g1CardTable.hpp | 1 - src/hotspot/share/gc/g1/g1ConcurrentMarkThread.hpp | 2 -- src/hotspot/share/gc/g1/g1ConcurrentRefineThread.hpp | 1 - src/hotspot/share/gc/g1/g1HeapRegionRemSet.hpp | 2 -- src/hotspot/share/gc/g1/g1PageBasedVirtualSpace.hpp | 1 - src/hotspot/share/gc/parallel/mutableNUMASpace.hpp | 2 -- src/hotspot/share/gc/serial/cSpaceCounters.hpp | 2 -- src/hotspot/share/gc/shared/collectorCounters.hpp | 2 -- src/hotspot/share/gc/shared/gcPolicyCounters.hpp | 2 -- src/hotspot/share/gc/shared/generationCounters.hpp | 2 -- src/hotspot/share/gc/shared/hSpaceCounters.hpp | 2 -- src/hotspot/share/gc/shared/scavengableNMethods.hpp | 2 -- src/hotspot/share/gc/shared/stringdedup/stringDedupThread.hpp | 2 -- src/hotspot/share/gc/shenandoah/shenandoahCardTable.hpp | 2 -- src/hotspot/share/gc/shenandoah/shenandoahControlThread.hpp | 2 -- .../gc/shenandoah/shenandoahGenerationalControlThread.hpp | 2 -- src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.hpp | 2 -- src/hotspot/share/interpreter/templateInterpreter.hpp | 1 - src/hotspot/share/interpreter/zero/bytecodeInterpreter.hpp | 1 - src/hotspot/share/interpreter/zero/zeroInterpreter.hpp | 1 - src/hotspot/share/memory/heap.hpp | 1 - src/hotspot/share/memory/metaspaceCounters.cpp | 1 - src/hotspot/share/oops/instanceClassLoaderKlass.hpp | 1 - src/hotspot/share/oops/instanceMirrorKlass.hpp | 1 - src/hotspot/share/oops/instanceStackChunkKlass.hpp | 1 - src/hotspot/share/opto/matcher.hpp | 2 -- src/hotspot/share/opto/parse.hpp | 2 -- src/hotspot/share/runtime/java.hpp | 1 - src/hotspot/share/runtime/monitorDeflationThread.hpp | 1 - src/hotspot/share/runtime/nonJavaThread.hpp | 3 --- src/hotspot/share/runtime/notificationThread.hpp | 1 - src/hotspot/share/runtime/os.hpp | 1 - src/hotspot/share/runtime/serviceThread.hpp | 1 - src/hotspot/share/runtime/vmStructs.cpp | 4 ---- src/hotspot/share/utilities/growableArray.hpp | 3 +-- 47 files changed, 2 insertions(+), 79 deletions(-) diff --git a/src/hotspot/share/ci/ciObjectFactory.hpp b/src/hotspot/share/ci/ciObjectFactory.hpp index 15ff2e48eb6..fd7ca6bb801 100644 --- a/src/hotspot/share/ci/ciObjectFactory.hpp +++ b/src/hotspot/share/ci/ciObjectFactory.hpp @@ -37,7 +37,6 @@ // which ensures that for each oop, at most one ciObject is created. // This invariant allows efficient implementation of ciObject. class ciObjectFactory : public ArenaObj { - friend class VMStructs; friend class ciEnv; private: diff --git a/src/hotspot/share/classfile/compactHashtable.hpp b/src/hotspot/share/classfile/compactHashtable.hpp index cb241ef5e70..402c8f197fa 100644 --- a/src/hotspot/share/classfile/compactHashtable.hpp +++ b/src/hotspot/share/classfile/compactHashtable.hpp @@ -254,7 +254,6 @@ template < bool (*EQUALS)(V value, K key, int len) > class CompactHashtable : public SimpleCompactHashtable { - friend class VMStructs; V decode(u4 encoded_value) const { return DECODE(_base_address, encoded_value); diff --git a/src/hotspot/share/code/codeBlob.hpp b/src/hotspot/share/code/codeBlob.hpp index 0b4760e7e1e..0469b6c71b1 100644 --- a/src/hotspot/share/code/codeBlob.hpp +++ b/src/hotspot/share/code/codeBlob.hpp @@ -325,7 +325,6 @@ public: // RuntimeBlob: used for non-compiled method code (adapters, stubs, blobs) class RuntimeBlob : public CodeBlob { - friend class VMStructs; public: // Creation @@ -634,7 +633,6 @@ class DeoptimizationBlob: public SingletonBlob { #ifdef COMPILER2 class UncommonTrapBlob: public SingletonBlob { - friend class VMStructs; private: // Creation support UncommonTrapBlob( @@ -658,7 +656,6 @@ class UncommonTrapBlob: public SingletonBlob { // ExceptionBlob: used for exception unwinding in compiled code (currently only used by Compiler 2) class ExceptionBlob: public SingletonBlob { - friend class VMStructs; private: // Creation support ExceptionBlob( @@ -695,7 +692,6 @@ class ExceptionBlob: public SingletonBlob { // SafepointBlob: handles illegal_instruction exceptions during a safepoint class SafepointBlob: public SingletonBlob { - friend class VMStructs; private: // Creation support SafepointBlob( diff --git a/src/hotspot/share/code/dependencyContext.hpp b/src/hotspot/share/code/dependencyContext.hpp index 7e8f7163509..b08300ec645 100644 --- a/src/hotspot/share/code/dependencyContext.hpp +++ b/src/hotspot/share/code/dependencyContext.hpp @@ -42,7 +42,6 @@ class DepChange; // finding nmethods which might need to be deoptimized. // class nmethodBucket: public CHeapObj { - friend class VMStructs; private: nmethod* _nmethod; nmethodBucket* volatile _next; @@ -68,7 +67,6 @@ class nmethodBucket: public CHeapObj { // and uint64_t integer recording the safepoint counter at the last cleanup. // class DependencyContext : public StackObj { - friend class VMStructs; friend class TestDependencyContext; private: nmethodBucket* volatile* _dependency_context_addr; diff --git a/src/hotspot/share/code/nmethod.hpp b/src/hotspot/share/code/nmethod.hpp index 020370c504b..8dfccb07891 100644 --- a/src/hotspot/share/code/nmethod.hpp +++ b/src/hotspot/share/code/nmethod.hpp @@ -90,7 +90,6 @@ class ExceptionCache : public CHeapObj { // cache pc descs found in earlier inquiries class PcDescCache { - friend class VMStructs; private: enum { cache_size = 4 }; // The array elements MUST be volatile! Several threads may modify diff --git a/src/hotspot/share/compiler/abstractCompiler.hpp b/src/hotspot/share/compiler/abstractCompiler.hpp index d61ae639c3f..adc85efbed5 100644 --- a/src/hotspot/share/compiler/abstractCompiler.hpp +++ b/src/hotspot/share/compiler/abstractCompiler.hpp @@ -33,8 +33,6 @@ typedef void (*initializer)(void); // Per-compiler statistics class CompilerStatistics { - friend class VMStructs; - class Data { friend class VMStructs; public: diff --git a/src/hotspot/share/compiler/oopMap.hpp b/src/hotspot/share/compiler/oopMap.hpp index 4b962444738..ef8845ac9aa 100644 --- a/src/hotspot/share/compiler/oopMap.hpp +++ b/src/hotspot/share/compiler/oopMap.hpp @@ -479,7 +479,6 @@ private: // pointers are updated based on their base pointers new value and an offset. #if COMPILER2_OR_JVMCI class DerivedPointerTable : public AllStatic { - friend class VMStructs; private: class Entry; static bool _active; // do not record pointers for verify pass etc. diff --git a/src/hotspot/share/gc/epsilon/epsilonBarrierSet.hpp b/src/hotspot/share/gc/epsilon/epsilonBarrierSet.hpp index 7a8083df6bb..c146ff39680 100644 --- a/src/hotspot/share/gc/epsilon/epsilonBarrierSet.hpp +++ b/src/hotspot/share/gc/epsilon/epsilonBarrierSet.hpp @@ -30,8 +30,6 @@ // No interaction with application is required for Epsilon, and therefore // the barrier set is empty. class EpsilonBarrierSet: public BarrierSet { - friend class VMStructs; - public: EpsilonBarrierSet(); diff --git a/src/hotspot/share/gc/epsilon/epsilonMonitoringSupport.cpp b/src/hotspot/share/gc/epsilon/epsilonMonitoringSupport.cpp index 33a2690f777..51d0a8356d2 100644 --- a/src/hotspot/share/gc/epsilon/epsilonMonitoringSupport.cpp +++ b/src/hotspot/share/gc/epsilon/epsilonMonitoringSupport.cpp @@ -32,8 +32,6 @@ #include "services/memoryService.hpp" class EpsilonSpaceCounters: public CHeapObj { - friend class VMStructs; - private: PerfVariable* _capacity; PerfVariable* _used; diff --git a/src/hotspot/share/gc/g1/g1Allocator.hpp b/src/hotspot/share/gc/g1/g1Allocator.hpp index 8c382824b27..19b19c06e92 100644 --- a/src/hotspot/share/gc/g1/g1Allocator.hpp +++ b/src/hotspot/share/gc/g1/g1Allocator.hpp @@ -37,8 +37,6 @@ class G1NUMA; // some accessors (e.g. allocating into them, or getting their occupancy). // Also keeps track of retained regions across GCs. class G1Allocator : public CHeapObj { - friend class VMStructs; - private: G1CollectedHeap* _g1h; G1NUMA* _numa; diff --git a/src/hotspot/share/gc/g1/g1BarrierSet.hpp b/src/hotspot/share/gc/g1/g1BarrierSet.hpp index 40e87c373b7..20642cfc7e6 100644 --- a/src/hotspot/share/gc/g1/g1BarrierSet.hpp +++ b/src/hotspot/share/gc/g1/g1BarrierSet.hpp @@ -62,7 +62,6 @@ class Thread; // cards. // class G1BarrierSet: public CardTableBarrierSet { - friend class VMStructs; private: BufferNode::Allocator _satb_mark_queue_buffer_allocator; G1SATBMarkQueueSet _satb_mark_queue_set; diff --git a/src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp b/src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp index 59d5c4efcef..3b97efc4f0f 100644 --- a/src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp +++ b/src/hotspot/share/gc/g1/g1BlockOffsetTable.hpp @@ -35,9 +35,7 @@ // into "N"-word subregions (where "N" = 2^"LogN". An array with an entry // for each such subregion indicates how far back one must go to find the // start of the chunk that includes the first word of the subregion. -class G1BlockOffsetTable: public CHeapObj { - friend class VMStructs; - +class G1BlockOffsetTable : public CHeapObj { private: // The reserved region covered by the table. MemRegion _reserved; diff --git a/src/hotspot/share/gc/g1/g1CardTable.hpp b/src/hotspot/share/gc/g1/g1CardTable.hpp index 060e5459778..ddbfa841c24 100644 --- a/src/hotspot/share/gc/g1/g1CardTable.hpp +++ b/src/hotspot/share/gc/g1/g1CardTable.hpp @@ -45,7 +45,6 @@ class G1CardTableChangedListener : public G1MappingChangedListener { }; class G1CardTable : public CardTable { - friend class VMStructs; friend class G1CardTableChangedListener; G1CardTableChangedListener _listener; diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.hpp b/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.hpp index 5f9ec4ef404..22be7d9ffbb 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.hpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMarkThread.hpp @@ -33,8 +33,6 @@ class G1Policy; // The concurrent mark thread triggers the various steps of the concurrent marking // cycle, including various marking cleanup. class G1ConcurrentMarkThread: public ConcurrentGCThread { - friend class VMStructs; - G1ConcurrentMark* _cm; enum ServiceState : uint { diff --git a/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.hpp b/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.hpp index 8e635247cd3..7cdc001d348 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.hpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentRefineThread.hpp @@ -36,7 +36,6 @@ class G1ConcurrentRefine; // Concurrent refinement control thread watching card mark accrual on the card table // and starting refinement work. class G1ConcurrentRefineThread: public ConcurrentGCThread { - friend class VMStructs; friend class G1CollectedHeap; Monitor _notifier; diff --git a/src/hotspot/share/gc/g1/g1HeapRegionRemSet.hpp b/src/hotspot/share/gc/g1/g1HeapRegionRemSet.hpp index 023216f989d..0f78e0d6271 100644 --- a/src/hotspot/share/gc/g1/g1HeapRegionRemSet.hpp +++ b/src/hotspot/share/gc/g1/g1HeapRegionRemSet.hpp @@ -40,8 +40,6 @@ class G1CSetCandidateGroup; class outputStream; class G1HeapRegionRemSet : public CHeapObj { - friend class VMStructs; - // A set of nmethods whose code contains pointers into // the region that owns this RSet. G1CodeRootSet _code_roots; diff --git a/src/hotspot/share/gc/g1/g1PageBasedVirtualSpace.hpp b/src/hotspot/share/gc/g1/g1PageBasedVirtualSpace.hpp index 303acf62d0b..15155c1d668 100644 --- a/src/hotspot/share/gc/g1/g1PageBasedVirtualSpace.hpp +++ b/src/hotspot/share/gc/g1/g1PageBasedVirtualSpace.hpp @@ -45,7 +45,6 @@ class WorkerThreads; // The implementation gives an error when trying to commit or uncommit pages that // have already been committed or uncommitted. class G1PageBasedVirtualSpace { - friend class VMStructs; private: // Reserved area addresses. char* _low_boundary; diff --git a/src/hotspot/share/gc/parallel/mutableNUMASpace.hpp b/src/hotspot/share/gc/parallel/mutableNUMASpace.hpp index 3699dcde964..dc37b10292a 100644 --- a/src/hotspot/share/gc/parallel/mutableNUMASpace.hpp +++ b/src/hotspot/share/gc/parallel/mutableNUMASpace.hpp @@ -60,8 +60,6 @@ */ class MutableNUMASpace : public MutableSpace { - friend class VMStructs; - class LGRPSpace : public CHeapObj { uint _lgrp_id; MutableSpace* _space; diff --git a/src/hotspot/share/gc/serial/cSpaceCounters.hpp b/src/hotspot/share/gc/serial/cSpaceCounters.hpp index b378f379afe..14c68e2b397 100644 --- a/src/hotspot/share/gc/serial/cSpaceCounters.hpp +++ b/src/hotspot/share/gc/serial/cSpaceCounters.hpp @@ -33,8 +33,6 @@ // that track a space; class CSpaceCounters: public CHeapObj { - friend class VMStructs; - private: PerfVariable* _capacity; PerfVariable* _used; diff --git a/src/hotspot/share/gc/shared/collectorCounters.hpp b/src/hotspot/share/gc/shared/collectorCounters.hpp index 64e59db86e4..273f8fb2a4e 100644 --- a/src/hotspot/share/gc/shared/collectorCounters.hpp +++ b/src/hotspot/share/gc/shared/collectorCounters.hpp @@ -31,8 +31,6 @@ // that track a collector class CollectorCounters: public CHeapObj { - friend class VMStructs; - private: PerfCounter* _invocations; PerfCounter* _time; diff --git a/src/hotspot/share/gc/shared/gcPolicyCounters.hpp b/src/hotspot/share/gc/shared/gcPolicyCounters.hpp index 1f8026d21ac..e2ddb537f6e 100644 --- a/src/hotspot/share/gc/shared/gcPolicyCounters.hpp +++ b/src/hotspot/share/gc/shared/gcPolicyCounters.hpp @@ -31,8 +31,6 @@ // that track a generation class GCPolicyCounters: public CHeapObj { - friend class VMStructs; - // Constant PerfData types don't need to retain a reference. // However, it's a good idea to document them here. // PerfStringConstant* _name; diff --git a/src/hotspot/share/gc/shared/generationCounters.hpp b/src/hotspot/share/gc/shared/generationCounters.hpp index cb835b44e25..3985f40a3aa 100644 --- a/src/hotspot/share/gc/shared/generationCounters.hpp +++ b/src/hotspot/share/gc/shared/generationCounters.hpp @@ -32,8 +32,6 @@ // that track a generation class GenerationCounters: public CHeapObj { - friend class VMStructs; - PerfVariable* _current_size; // Constant PerfData types don't need to retain a reference. diff --git a/src/hotspot/share/gc/shared/hSpaceCounters.hpp b/src/hotspot/share/gc/shared/hSpaceCounters.hpp index 01310e456f6..b55b24f7601 100644 --- a/src/hotspot/share/gc/shared/hSpaceCounters.hpp +++ b/src/hotspot/share/gc/shared/hSpaceCounters.hpp @@ -33,8 +33,6 @@ // that track a collections (logical spaces) in a heap; class HSpaceCounters: public CHeapObj { - friend class VMStructs; - private: PerfVariable* _capacity; PerfVariable* _used; diff --git a/src/hotspot/share/gc/shared/scavengableNMethods.hpp b/src/hotspot/share/gc/shared/scavengableNMethods.hpp index 31093a0482c..00db556577e 100644 --- a/src/hotspot/share/gc/shared/scavengableNMethods.hpp +++ b/src/hotspot/share/gc/shared/scavengableNMethods.hpp @@ -33,8 +33,6 @@ class nmethod; class NMethodToOopClosure; class ScavengableNMethods : public AllStatic { - friend class VMStructs; - static nmethod* _head; static BoolObjectClosure* _is_scavengable; diff --git a/src/hotspot/share/gc/shared/stringdedup/stringDedupThread.hpp b/src/hotspot/share/gc/shared/stringdedup/stringDedupThread.hpp index 504e1fe617f..b1feb1b4ca9 100644 --- a/src/hotspot/share/gc/shared/stringdedup/stringDedupThread.hpp +++ b/src/hotspot/share/gc/shared/stringdedup/stringDedupThread.hpp @@ -38,8 +38,6 @@ // not an inner class of StringDedup. This is because we need a simple public // identifier for use by VMStructs. class StringDedupThread : public JavaThread { - friend class VMStructs; - StringDedupThread(); ~StringDedupThread() = default; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahCardTable.hpp b/src/hotspot/share/gc/shenandoah/shenandoahCardTable.hpp index 33a4705b8d2..69b5a1abf72 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahCardTable.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahCardTable.hpp @@ -33,8 +33,6 @@ #define ShenandoahMinCardSizeInBytes 128 class ShenandoahCardTable: public CardTable { - friend class VMStructs; - private: // We maintain two copies of the card table to facilitate concurrent remembered set scanning // and concurrent clearing of stale remembered set information. During the init_mark safepoint, diff --git a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.hpp b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.hpp index 9d95b5df7ed..4975404bbaa 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahControlThread.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahControlThread.hpp @@ -33,8 +33,6 @@ #include "gc/shenandoah/shenandoahSharedVariables.hpp" class ShenandoahControlThread: public ShenandoahController { - friend class VMStructs; - private: typedef enum { none, diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.hpp index 6a4f5bde578..b7dbedd5e84 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.hpp @@ -38,8 +38,6 @@ class ShenandoahGenerationalHeap; class ShenandoahHeap; class ShenandoahGenerationalControlThread: public ShenandoahController { - friend class VMStructs; - public: typedef enum { none, diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.hpp b/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.hpp index a72d6004beb..c23690b15d6 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRegulatorThread.hpp @@ -45,8 +45,6 @@ class ShenandoahOldHeuristics; * sleep time. */ class ShenandoahRegulatorThread: public ConcurrentGCThread { - friend class VMStructs; - public: explicit ShenandoahRegulatorThread(ShenandoahGenerationalControlThread* control_thread); diff --git a/src/hotspot/share/interpreter/templateInterpreter.hpp b/src/hotspot/share/interpreter/templateInterpreter.hpp index 8f118bb6ec8..fd6888ffab8 100644 --- a/src/hotspot/share/interpreter/templateInterpreter.hpp +++ b/src/hotspot/share/interpreter/templateInterpreter.hpp @@ -84,7 +84,6 @@ class DispatchTable { }; class TemplateInterpreter: public AbstractInterpreter { - friend class VMStructs; friend class InterpreterMacroAssembler; friend class TemplateInterpreterGenerator; friend class TemplateTable; diff --git a/src/hotspot/share/interpreter/zero/bytecodeInterpreter.hpp b/src/hotspot/share/interpreter/zero/bytecodeInterpreter.hpp index 9941055bfd4..0032109982a 100644 --- a/src/hotspot/share/interpreter/zero/bytecodeInterpreter.hpp +++ b/src/hotspot/share/interpreter/zero/bytecodeInterpreter.hpp @@ -79,7 +79,6 @@ friend class AbstractInterpreterGenerator; friend class ZeroInterpreterGenerator; friend class InterpreterMacroAssembler; friend class frame; -friend class VMStructs; public: enum messages { diff --git a/src/hotspot/share/interpreter/zero/zeroInterpreter.hpp b/src/hotspot/share/interpreter/zero/zeroInterpreter.hpp index 4cc78532379..79528de639b 100644 --- a/src/hotspot/share/interpreter/zero/zeroInterpreter.hpp +++ b/src/hotspot/share/interpreter/zero/zeroInterpreter.hpp @@ -36,7 +36,6 @@ class InterpreterCodelet; // of the c++ interpreter class ZeroInterpreter: public AbstractInterpreter { - friend class VMStructs; public: // Initialization/debugging static void initialize_stub(); diff --git a/src/hotspot/share/memory/heap.hpp b/src/hotspot/share/memory/heap.hpp index 5056f0f6c21..9db8aae79cb 100644 --- a/src/hotspot/share/memory/heap.hpp +++ b/src/hotspot/share/memory/heap.hpp @@ -70,7 +70,6 @@ class HeapBlock { }; class FreeBlock: public HeapBlock { - friend class VMStructs; protected: FreeBlock* _link; diff --git a/src/hotspot/share/memory/metaspaceCounters.cpp b/src/hotspot/share/memory/metaspaceCounters.cpp index b57373516f9..7396ac78655 100644 --- a/src/hotspot/share/memory/metaspaceCounters.cpp +++ b/src/hotspot/share/memory/metaspaceCounters.cpp @@ -32,7 +32,6 @@ #include "utilities/exceptions.hpp" class MetaspacePerfCounters { - friend class VMStructs; PerfVariable* _capacity; PerfVariable* _used; PerfVariable* _max_capacity; diff --git a/src/hotspot/share/oops/instanceClassLoaderKlass.hpp b/src/hotspot/share/oops/instanceClassLoaderKlass.hpp index 985c81c3cd6..f6aedc312aa 100644 --- a/src/hotspot/share/oops/instanceClassLoaderKlass.hpp +++ b/src/hotspot/share/oops/instanceClassLoaderKlass.hpp @@ -37,7 +37,6 @@ class ClassFileParser; // the list later? class InstanceClassLoaderKlass: public InstanceKlass { - friend class VMStructs; friend class InstanceKlass; public: static const KlassKind Kind = InstanceClassLoaderKlassKind; diff --git a/src/hotspot/share/oops/instanceMirrorKlass.hpp b/src/hotspot/share/oops/instanceMirrorKlass.hpp index e9928647db9..4546f904eca 100644 --- a/src/hotspot/share/oops/instanceMirrorKlass.hpp +++ b/src/hotspot/share/oops/instanceMirrorKlass.hpp @@ -41,7 +41,6 @@ class ClassFileParser; class InstanceMirrorKlass: public InstanceKlass { - friend class VMStructs; friend class InstanceKlass; public: diff --git a/src/hotspot/share/oops/instanceStackChunkKlass.hpp b/src/hotspot/share/oops/instanceStackChunkKlass.hpp index 19ce37c4ddd..5afbc5d00eb 100644 --- a/src/hotspot/share/oops/instanceStackChunkKlass.hpp +++ b/src/hotspot/share/oops/instanceStackChunkKlass.hpp @@ -100,7 +100,6 @@ Chunk layout: class InstanceStackChunkKlass: public InstanceKlass { - friend class VMStructs; friend class InstanceKlass; friend class Continuations; diff --git a/src/hotspot/share/opto/matcher.hpp b/src/hotspot/share/opto/matcher.hpp index 2ee2ded17b6..f4b0a7db873 100644 --- a/src/hotspot/share/opto/matcher.hpp +++ b/src/hotspot/share/opto/matcher.hpp @@ -43,8 +43,6 @@ class MachOper; //---------------------------Matcher------------------------------------------- class Matcher : public PhaseTransform { - friend class VMStructs; - public: // Machine-dependent definitions diff --git a/src/hotspot/share/opto/parse.hpp b/src/hotspot/share/opto/parse.hpp index 83b211828ce..19b302a8924 100644 --- a/src/hotspot/share/opto/parse.hpp +++ b/src/hotspot/share/opto/parse.hpp @@ -41,8 +41,6 @@ class SwitchRange; //------------------------------InlineTree------------------------------------- class InlineTree : public AnyObj { - friend class VMStructs; - Compile* C; // cache JVMState* _caller_jvms; // state of caller ciMethod* _method; // method being called by the caller_jvms diff --git a/src/hotspot/share/runtime/java.hpp b/src/hotspot/share/runtime/java.hpp index 21cbd76431f..67cf3fb686a 100644 --- a/src/hotspot/share/runtime/java.hpp +++ b/src/hotspot/share/runtime/java.hpp @@ -68,7 +68,6 @@ extern bool is_vm_statically_linked(); * string prior to JDK 1.6 was removed (partial initialization) */ class JDK_Version { - friend class VMStructs; friend class Universe; friend void JDK_Version_init(); private: diff --git a/src/hotspot/share/runtime/monitorDeflationThread.hpp b/src/hotspot/share/runtime/monitorDeflationThread.hpp index c0ae9dd2d6f..6b681617a4c 100644 --- a/src/hotspot/share/runtime/monitorDeflationThread.hpp +++ b/src/hotspot/share/runtime/monitorDeflationThread.hpp @@ -30,7 +30,6 @@ // A hidden from external view JavaThread for deflating idle monitors. class MonitorDeflationThread : public JavaThread { - friend class VMStructs; private: static void monitor_deflation_thread_entry(JavaThread* thread, TRAPS); diff --git a/src/hotspot/share/runtime/nonJavaThread.hpp b/src/hotspot/share/runtime/nonJavaThread.hpp index 6d9095924d9..b2ac6a31737 100644 --- a/src/hotspot/share/runtime/nonJavaThread.hpp +++ b/src/hotspot/share/runtime/nonJavaThread.hpp @@ -28,8 +28,6 @@ #include "runtime/thread.hpp" class NonJavaThread: public Thread { - friend class VMStructs; - NonJavaThread* volatile _next; class List; @@ -103,7 +101,6 @@ class NamedThread: public NonJavaThread { // A single WatcherThread is used for simulating timer interrupts. class WatcherThread: public NonJavaThread { - friend class VMStructs; protected: virtual void run(); diff --git a/src/hotspot/share/runtime/notificationThread.hpp b/src/hotspot/share/runtime/notificationThread.hpp index 17977e93539..e8e72052e4a 100644 --- a/src/hotspot/share/runtime/notificationThread.hpp +++ b/src/hotspot/share/runtime/notificationThread.hpp @@ -33,7 +33,6 @@ // breakpoints inside registered MXBean notification listeners. class NotificationThread : public JavaThread { - friend class VMStructs; private: static void notification_thread_entry(JavaThread* thread, TRAPS); diff --git a/src/hotspot/share/runtime/os.hpp b/src/hotspot/share/runtime/os.hpp index 76695de2c1b..e008f29eecc 100644 --- a/src/hotspot/share/runtime/os.hpp +++ b/src/hotspot/share/runtime/os.hpp @@ -168,7 +168,6 @@ public: }; class os: AllStatic { - friend class VMStructs; friend class JVMCIVMStructs; friend class MallocTracker; diff --git a/src/hotspot/share/runtime/serviceThread.hpp b/src/hotspot/share/runtime/serviceThread.hpp index d029c64590e..f65847ece00 100644 --- a/src/hotspot/share/runtime/serviceThread.hpp +++ b/src/hotspot/share/runtime/serviceThread.hpp @@ -34,7 +34,6 @@ class JvmtiDeferredEvent; class ServiceThread : public JavaThread { - friend class VMStructs; private: DEBUG_ONLY(static JavaThread* _instance;) static JvmtiDeferredEvent* _jvmti_event; diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index 10069e849bc..5a3850feac8 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -58,11 +58,8 @@ #include "oops/constMethod.hpp" #include "oops/cpCache.hpp" #include "oops/fieldInfo.hpp" -#include "oops/instanceClassLoaderKlass.hpp" #include "oops/instanceKlass.hpp" -#include "oops/instanceMirrorKlass.hpp" #include "oops/instanceOop.hpp" -#include "oops/instanceStackChunkKlass.hpp" #include "oops/klass.hpp" #include "oops/klassVtable.hpp" #include "oops/markWord.hpp" @@ -84,7 +81,6 @@ #include "runtime/deoptimization.hpp" #include "runtime/flags/jvmFlag.hpp" #include "runtime/globals.hpp" -#include "runtime/java.hpp" #include "runtime/javaCalls.hpp" #include "runtime/javaThread.hpp" #include "runtime/jniHandles.hpp" diff --git a/src/hotspot/share/utilities/growableArray.hpp b/src/hotspot/share/utilities/growableArray.hpp index 53403ca5cf1..1fef271c8c0 100644 --- a/src/hotspot/share/utilities/growableArray.hpp +++ b/src/hotspot/share/utilities/growableArray.hpp @@ -317,8 +317,6 @@ public: // - void Derived::deallocate(E*) - member function responsible for deallocation template class GrowableArrayWithAllocator : public GrowableArrayView { - friend class VMStructs; - void expand_to(int j); void grow(int j); @@ -714,6 +712,7 @@ public: template class GrowableArray : public GrowableArrayWithAllocator> { + friend class VMStructs; friend class GrowableArrayWithAllocator; friend class GrowableArrayTest; From 8be16160d2a6275ff619ea4cebb725475c646052 Mon Sep 17 00:00:00 2001 From: Francesco Andreuzzi Date: Thu, 2 Oct 2025 11:41:30 +0000 Subject: [PATCH 0033/1639] 8367609: serviceability/sa/ClhsdbPmap.java fails when built with Clang Reviewed-by: kevinw, cjplummer --- src/jdk.hotspot.agent/linux/native/libsaproc/ps_core.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/jdk.hotspot.agent/linux/native/libsaproc/ps_core.c b/src/jdk.hotspot.agent/linux/native/libsaproc/ps_core.c index c3aaaf440a3..9c4f0b0d357 100644 --- a/src/jdk.hotspot.agent/linux/native/libsaproc/ps_core.c +++ b/src/jdk.hotspot.agent/linux/native/libsaproc/ps_core.c @@ -420,9 +420,15 @@ static bool read_lib_segments(struct ps_prochandle* ph, int lib_fd, ELF_EHDR* li // Coredump stores value of p_memsz elf field // rounded up to page boundary. + // Account for the PH being at some vaddr offset from mapping in core file. + uint64_t lib_memsz = lib_php->p_memsz; + if (target_vaddr > existing_map->vaddr) { + lib_memsz += target_vaddr - existing_map->vaddr; + } + if ((existing_map->memsz != page_size) && (existing_map->fd != lib_fd) && - (ROUNDUP(existing_map->memsz, page_size) != ROUNDUP(lib_php->p_memsz, page_size))) { + (ROUNDUP(existing_map->memsz, page_size) != ROUNDUP(lib_memsz, page_size))) { print_error("address conflict @ 0x%lx (existing map size = %ld, size = %ld, flags = %d)\n", target_vaddr, existing_map->memsz, lib_php->p_memsz, lib_php->p_flags); From cc563c87cd277fbc96fb77af1e99f6c018ccc020 Mon Sep 17 00:00:00 2001 From: SendaoYan Date: Thu, 2 Oct 2025 12:37:27 +0000 Subject: [PATCH 0034/1639] 8368866: compiler/codecache/stress/UnexpectedDeoptimizationTest.java intermittent timed out Reviewed-by: shade, mhaessig --- .../stress/UnexpectedDeoptimizationTest.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/test/hotspot/jtreg/compiler/codecache/stress/UnexpectedDeoptimizationTest.java b/test/hotspot/jtreg/compiler/codecache/stress/UnexpectedDeoptimizationTest.java index b3def9455c4..5ad047c826e 100644 --- a/test/hotspot/jtreg/compiler/codecache/stress/UnexpectedDeoptimizationTest.java +++ b/test/hotspot/jtreg/compiler/codecache/stress/UnexpectedDeoptimizationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,26 +31,26 @@ * * @build jdk.test.whitebox.WhiteBox compiler.codecache.stress.Helper compiler.codecache.stress.TestCaseImpl * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * @run main/othervm/timeout=240 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI * -XX:+IgnoreUnrecognizedVMOptions -XX:-DeoptimizeRandom * -XX:CompileCommand=dontinline,compiler.codecache.stress.Helper$TestCase::method * -XX:-SegmentedCodeCache * compiler.codecache.stress.UnexpectedDeoptimizationTest - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * @run main/othervm/timeout=240 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI * -XX:+IgnoreUnrecognizedVMOptions -XX:-DeoptimizeRandom * -XX:CompileCommand=dontinline,compiler.codecache.stress.Helper$TestCase::method * -XX:+SegmentedCodeCache * compiler.codecache.stress.UnexpectedDeoptimizationTest - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * @run main/othervm/timeout=240 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI * -XX:+IgnoreUnrecognizedVMOptions -XX:-DeoptimizeRandom * -XX:CompileCommand=dontinline,compiler.codecache.stress.Helper$TestCase::method * -XX:-SegmentedCodeCache * -DhelperVirtualThread=true * compiler.codecache.stress.UnexpectedDeoptimizationTest - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions + * @run main/othervm/timeout=240 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI * -XX:+IgnoreUnrecognizedVMOptions -XX:-DeoptimizeRandom * -XX:CompileCommand=dontinline,compiler.codecache.stress.Helper$TestCase::method @@ -75,7 +75,7 @@ public class UnexpectedDeoptimizationTest implements Runnable { public void run() { Helper.WHITE_BOX.deoptimizeFrames(rng.nextBoolean()); // Sleep a short while to allow the stacks to grow - otherwise - // we end up running almost all code in the interpreter + // we end up running almost all code in the interpreter try { Thread.sleep(10); } catch (Exception e) { From 56baf64ada04f233fbfe4e0cd033c86183e22015 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Jeli=C5=84ski?= Date: Thu, 2 Oct 2025 13:29:45 +0000 Subject: [PATCH 0035/1639] 8368520: TLS 1.3 KeyUpdate fails with SunPKCS11 provider Reviewed-by: valeriep --- .../security/ssl/SSLTrafficKeyDerivation.java | 22 +++++++++---------- .../security/pkcs11/tls/fips/FipsModeTLS.java | 10 ++++++--- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/java.base/share/classes/sun/security/ssl/SSLTrafficKeyDerivation.java b/src/java.base/share/classes/sun/security/ssl/SSLTrafficKeyDerivation.java index 1db07c77160..5cb78ed44f7 100644 --- a/src/java.base/share/classes/sun/security/ssl/SSLTrafficKeyDerivation.java +++ b/src/java.base/share/classes/sun/security/ssl/SSLTrafficKeyDerivation.java @@ -29,13 +29,11 @@ import java.io.IOException; import java.nio.ByteBuffer; import java.security.GeneralSecurityException; import java.security.ProviderException; -import java.security.spec.AlgorithmParameterSpec; import javax.crypto.KDF; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.HKDFParameterSpec; import javax.crypto.spec.IvParameterSpec; -import javax.crypto.spec.SecretKeySpec; import javax.net.ssl.SSLHandshakeException; import sun.security.internal.spec.TlsKeyMaterialParameterSpec; import sun.security.internal.spec.TlsKeyMaterialSpec; @@ -191,26 +189,26 @@ enum SSLTrafficKeyDerivation implements SSLKeyDerivationGenerator { private enum KeySchedule { // Note that we use enum name as the key name. - TlsKey ("key", false), - TlsIv ("iv", true), - TlsUpdateNplus1 ("traffic upd", false); + TlsKey ("key"), + TlsIv ("iv"), + TlsUpdateNplus1 ("traffic upd"); private final byte[] label; - private final boolean isIv; - KeySchedule(String label, boolean isIv) { + KeySchedule(String label) { this.label = ("tls13 " + label).getBytes(); - this.isIv = isIv; } int getKeyLength(CipherSuite cs) { - if (this == KeySchedule.TlsUpdateNplus1) - return cs.hashAlg.hashLength; - return isIv ? cs.bulkCipher.ivSize : cs.bulkCipher.keySize; + return switch (this) { + case TlsUpdateNplus1 -> cs.hashAlg.hashLength; + case TlsIv -> cs.bulkCipher.ivSize; + case TlsKey -> cs.bulkCipher.keySize; + }; } String getAlgorithm(CipherSuite cs, String algorithm) { - return isIv ? algorithm : cs.bulkCipher.algorithm; + return this == TlsKey ? cs.bulkCipher.algorithm : algorithm; } } diff --git a/test/jdk/sun/security/pkcs11/tls/fips/FipsModeTLS.java b/test/jdk/sun/security/pkcs11/tls/fips/FipsModeTLS.java index a883239281c..c227e99d12b 100644 --- a/test/jdk/sun/security/pkcs11/tls/fips/FipsModeTLS.java +++ b/test/jdk/sun/security/pkcs11/tls/fips/FipsModeTLS.java @@ -24,7 +24,7 @@ /* * @test - * @bug 8029661 8325164 8368073 8368514 + * @bug 8029661 8325164 8368073 8368514 8368520 * @summary Test TLS 1.2 and TLS 1.3 * @modules java.base/sun.security.internal.spec * java.base/sun.security.util @@ -88,6 +88,9 @@ public final class FipsModeTLS extends SecmodTest { private static PublicKey publicKey; public static void main(String[] args) throws Exception { + // reduce the limit to trigger a key update later + Security.setProperty("jdk.tls.keyLimits", + "AES/GCM/NoPadding KeyUpdate 10000"); try { initialize(); } catch (Exception e) { @@ -305,10 +308,11 @@ public final class FipsModeTLS extends SecmodTest { cTOs = ByteBuffer.allocateDirect(netBufferMax); sTOc = ByteBuffer.allocateDirect(netBufferMax); + // big enough to trigger a key update clientOut = ByteBuffer.wrap( - "Hi Server, I'm Client".getBytes()); + "a".repeat(16000).getBytes()); serverOut = ByteBuffer.wrap( - "Hello Client, I'm Server".getBytes()); + "b".repeat(16000).getBytes()); SSLEngineResult clientResult; SSLEngineResult serverResult; From 2c7f7380ea828e5ec928e1cb05b13806646ecb3d Mon Sep 17 00:00:00 2001 From: Shaojin Wen Date: Thu, 2 Oct 2025 13:32:09 +0000 Subject: [PATCH 0036/1639] 8368825: Use switch expression for DateTimeFormatterBuilder pattern character lookup Reviewed-by: rriggs, naoto, scolebourne --- .../time/format/DateTimeFormatterBuilder.java | 91 ++++++++++--------- 1 file changed, 49 insertions(+), 42 deletions(-) diff --git a/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java b/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java index 7a2142e5113..9f5b82775b9 100644 --- a/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java +++ b/src/java.base/share/classes/java/time/format/DateTimeFormatterBuilder.java @@ -1937,7 +1937,7 @@ public final class DateTimeFormatterBuilder { padNext(pad); // pad and continue parsing } // main rules - TemporalField field = FIELD_MAP.get(cur); + TemporalField field = getField(cur); if (field != null) { parseField(cur, count, field); } else if (cur == 'z') { @@ -2185,48 +2185,55 @@ public final class DateTimeFormatterBuilder { } } - /** Map of letters to fields. */ - private static final Map FIELD_MAP = new HashMap<>(); - static { + /** + * Returns the TemporalField for the given pattern character. + * + * @param ch the pattern character + * @return the TemporalField for the given pattern character, or null if not applicable + */ + private static TemporalField getField(char ch) { // SDF = SimpleDateFormat - FIELD_MAP.put('G', ChronoField.ERA); // SDF, LDML (different to both for 1/2 chars) - FIELD_MAP.put('y', ChronoField.YEAR_OF_ERA); // SDF, LDML - FIELD_MAP.put('u', ChronoField.YEAR); // LDML (different in SDF) - FIELD_MAP.put('Q', IsoFields.QUARTER_OF_YEAR); // LDML (removed quarter from 310) - FIELD_MAP.put('q', IsoFields.QUARTER_OF_YEAR); // LDML (stand-alone) - FIELD_MAP.put('M', ChronoField.MONTH_OF_YEAR); // SDF, LDML - FIELD_MAP.put('L', ChronoField.MONTH_OF_YEAR); // SDF, LDML (stand-alone) - FIELD_MAP.put('D', ChronoField.DAY_OF_YEAR); // SDF, LDML - FIELD_MAP.put('d', ChronoField.DAY_OF_MONTH); // SDF, LDML - FIELD_MAP.put('F', ChronoField.ALIGNED_WEEK_OF_MONTH); // SDF, LDML - FIELD_MAP.put('E', ChronoField.DAY_OF_WEEK); // SDF, LDML (different to both for 1/2 chars) - FIELD_MAP.put('c', ChronoField.DAY_OF_WEEK); // LDML (stand-alone) - FIELD_MAP.put('e', ChronoField.DAY_OF_WEEK); // LDML (needs localized week number) - FIELD_MAP.put('a', ChronoField.AMPM_OF_DAY); // SDF, LDML - FIELD_MAP.put('H', ChronoField.HOUR_OF_DAY); // SDF, LDML - FIELD_MAP.put('k', ChronoField.CLOCK_HOUR_OF_DAY); // SDF, LDML - FIELD_MAP.put('K', ChronoField.HOUR_OF_AMPM); // SDF, LDML - FIELD_MAP.put('h', ChronoField.CLOCK_HOUR_OF_AMPM); // SDF, LDML - FIELD_MAP.put('m', ChronoField.MINUTE_OF_HOUR); // SDF, LDML - FIELD_MAP.put('s', ChronoField.SECOND_OF_MINUTE); // SDF, LDML - FIELD_MAP.put('S', ChronoField.NANO_OF_SECOND); // LDML (SDF uses milli-of-second number) - FIELD_MAP.put('A', ChronoField.MILLI_OF_DAY); // LDML - FIELD_MAP.put('n', ChronoField.NANO_OF_SECOND); // 310 (proposed for LDML) - FIELD_MAP.put('N', ChronoField.NANO_OF_DAY); // 310 (proposed for LDML) - FIELD_MAP.put('g', JulianFields.MODIFIED_JULIAN_DAY); - // 310 - z - time-zone names, matches LDML and SimpleDateFormat 1 to 4 - // 310 - Z - matches SimpleDateFormat and LDML - // 310 - V - time-zone id, matches LDML - // 310 - v - general timezone names, not matching exactly with LDML because LDML specify to fall back - // to 'VVVV' if general-nonlocation unavailable but here it's not falling back because of lack of data - // 310 - p - prefix for padding - // 310 - X - matches LDML, almost matches SDF for 1, exact match 2&3, extended 4&5 - // 310 - x - matches LDML - // 310 - w, W, and Y are localized forms matching LDML - // LDML - B - day periods - // LDML - U - cycle year name, not supported by 310 yet - // LDML - l - deprecated - // LDML - j - not relevant + return switch (ch) { + case 'G' -> ChronoField.ERA; // SDF, LDML (different to both for 1/2 chars) + case 'y' -> ChronoField.YEAR_OF_ERA; // SDF, LDML + case 'u' -> ChronoField.YEAR; // LDML (different in SDF) + case 'Q' -> IsoFields.QUARTER_OF_YEAR; // LDML (removed quarter from 310) + case 'q' -> IsoFields.QUARTER_OF_YEAR; // LDML (stand-alone) + case 'M' -> ChronoField.MONTH_OF_YEAR; // SDF, LDML + case 'L' -> ChronoField.MONTH_OF_YEAR; // SDF, LDML (stand-alone) + case 'D' -> ChronoField.DAY_OF_YEAR; // SDF, LDML + case 'd' -> ChronoField.DAY_OF_MONTH; // SDF, LDML + case 'F' -> ChronoField.ALIGNED_WEEK_OF_MONTH; // SDF, LDML + case 'E' -> ChronoField.DAY_OF_WEEK; // SDF, LDML (different to both for 1/2 chars) + case 'c' -> ChronoField.DAY_OF_WEEK; // LDML (stand-alone) + case 'e' -> ChronoField.DAY_OF_WEEK; // LDML (needs localized week number) + case 'a' -> ChronoField.AMPM_OF_DAY; // SDF, LDML + case 'H' -> ChronoField.HOUR_OF_DAY; // SDF, LDML + case 'k' -> ChronoField.CLOCK_HOUR_OF_DAY; // SDF, LDML + case 'K' -> ChronoField.HOUR_OF_AMPM; // SDF, LDML + case 'h' -> ChronoField.CLOCK_HOUR_OF_AMPM; // SDF, LDML + case 'm' -> ChronoField.MINUTE_OF_HOUR; // SDF, LDML + case 's' -> ChronoField.SECOND_OF_MINUTE; // SDF, LDML + case 'S' -> ChronoField.NANO_OF_SECOND; // LDML (SDF uses milli-of-second number) + case 'A' -> ChronoField.MILLI_OF_DAY; // LDML + case 'n' -> ChronoField.NANO_OF_SECOND; // 310 (proposed for LDML) + case 'N' -> ChronoField.NANO_OF_DAY; // 310 (proposed for LDML) + case 'g' -> JulianFields.MODIFIED_JULIAN_DAY; + default -> null; + // 310 - z - time-zone names, matches LDML and SimpleDateFormat 1 to 4 + // 310 - Z - matches SimpleDateFormat and LDML + // 310 - V - time-zone id, matches LDML + // 310 - v - general timezone names, not matching exactly with LDML because LDML specify to fall back + // to 'VVVV' if general-nonlocation unavailable but here it's not falling back because of lack of data + // 310 - p - prefix for padding + // 310 - X - matches LDML, almost matches SDF for 1, exact match 2&3, extended 4&5 + // 310 - x - matches LDML + // 310 - w, W, and Y are localized forms matching LDML + // LDML - B - day periods + // LDML - U - cycle year name, not supported by 310 yet + // LDML - l - deprecated + // LDML - j - not relevant + }; } //----------------------------------------------------------------------- From 5252262349cccb09f693ebd431fe2987ec0917f0 Mon Sep 17 00:00:00 2001 From: Casper Norrbin Date: Thu, 2 Oct 2025 13:38:41 +0000 Subject: [PATCH 0037/1639] 8292984: Refactor internal container-related interfaces for clarity Reviewed-by: sgehwolf, eosterlund --- .../os/linux/cgroupSubsystem_linux.cpp | 28 ++++------- .../os/linux/cgroupSubsystem_linux.hpp | 16 +++---- .../os/linux/cgroupV1Subsystem_linux.cpp | 46 +++++++++---------- .../os/linux/cgroupV1Subsystem_linux.hpp | 10 ++-- .../os/linux/cgroupV2Subsystem_linux.cpp | 24 +++++----- .../os/linux/cgroupV2Subsystem_linux.hpp | 6 +-- src/hotspot/os/linux/osContainer_linux.cpp | 38 ++++++++++++--- src/hotspot/os/linux/osContainer_linux.hpp | 1 + src/hotspot/os/linux/os_linux.cpp | 44 +++++++----------- 9 files changed, 109 insertions(+), 104 deletions(-) diff --git a/src/hotspot/os/linux/cgroupSubsystem_linux.cpp b/src/hotspot/os/linux/cgroupSubsystem_linux.cpp index f935e2cbb9c..f5c4abeb4ca 100644 --- a/src/hotspot/os/linux/cgroupSubsystem_linux.cpp +++ b/src/hotspot/os/linux/cgroupSubsystem_linux.cpp @@ -665,15 +665,13 @@ int CgroupSubsystem::active_processor_count() { * -1 for unlimited * OSCONTAINER_ERROR for not supported */ -jlong CgroupSubsystem::memory_limit_in_bytes() { +jlong CgroupSubsystem::memory_limit_in_bytes(julong upper_bound) { CachingCgroupController* contrl = memory_controller(); CachedMetric* memory_limit = contrl->metrics_cache(); if (!memory_limit->should_check_metric()) { return memory_limit->value(); } - julong phys_mem = static_cast(os::Linux::physical_memory()); - log_trace(os, container)("total physical memory: " JULONG_FORMAT, phys_mem); - jlong mem_limit = contrl->controller()->read_memory_limit_in_bytes(phys_mem); + jlong mem_limit = contrl->controller()->read_memory_limit_in_bytes(upper_bound); // Update cached metric to avoid re-reading container settings too often memory_limit->set_value(mem_limit, OSCONTAINER_CACHE_TIMEOUT); return mem_limit; @@ -841,21 +839,16 @@ jlong CgroupController::limit_from_str(char* limit_str) { // CgroupSubsystem implementations -jlong CgroupSubsystem::memory_and_swap_limit_in_bytes() { - julong phys_mem = static_cast(os::Linux::physical_memory()); - julong host_swap = os::Linux::host_swap(); - return memory_controller()->controller()->memory_and_swap_limit_in_bytes(phys_mem, host_swap); +jlong CgroupSubsystem::memory_and_swap_limit_in_bytes(julong upper_mem_bound, julong upper_swap_bound) { + return memory_controller()->controller()->memory_and_swap_limit_in_bytes(upper_mem_bound, upper_swap_bound); } -jlong CgroupSubsystem::memory_and_swap_usage_in_bytes() { - julong phys_mem = static_cast(os::Linux::physical_memory()); - julong host_swap = os::Linux::host_swap(); - return memory_controller()->controller()->memory_and_swap_usage_in_bytes(phys_mem, host_swap); +jlong CgroupSubsystem::memory_and_swap_usage_in_bytes(julong upper_mem_bound, julong upper_swap_bound) { + return memory_controller()->controller()->memory_and_swap_usage_in_bytes(upper_mem_bound, upper_swap_bound); } -jlong CgroupSubsystem::memory_soft_limit_in_bytes() { - julong phys_mem = static_cast(os::Linux::physical_memory()); - return memory_controller()->controller()->memory_soft_limit_in_bytes(phys_mem); +jlong CgroupSubsystem::memory_soft_limit_in_bytes(julong upper_bound) { + return memory_controller()->controller()->memory_soft_limit_in_bytes(upper_bound); } jlong CgroupSubsystem::memory_throttle_limit_in_bytes() { @@ -894,7 +887,6 @@ jlong CgroupSubsystem::cpu_usage_in_micros() { return cpuacct_controller()->cpu_usage_in_micros(); } -void CgroupSubsystem::print_version_specific_info(outputStream* st) { - julong phys_mem = static_cast(os::Linux::physical_memory()); - memory_controller()->controller()->print_version_specific_info(st, phys_mem); +void CgroupSubsystem::print_version_specific_info(outputStream* st, julong upper_mem_bound) { + memory_controller()->controller()->print_version_specific_info(st, upper_mem_bound); } diff --git a/src/hotspot/os/linux/cgroupSubsystem_linux.hpp b/src/hotspot/os/linux/cgroupSubsystem_linux.hpp index 22e57d56c93..62a61432665 100644 --- a/src/hotspot/os/linux/cgroupSubsystem_linux.hpp +++ b/src/hotspot/os/linux/cgroupSubsystem_linux.hpp @@ -233,14 +233,14 @@ class CgroupMemoryController: public CHeapObj { public: virtual jlong read_memory_limit_in_bytes(julong upper_bound) = 0; virtual jlong memory_usage_in_bytes() = 0; - virtual jlong memory_and_swap_limit_in_bytes(julong host_mem, julong host_swap) = 0; - virtual jlong memory_and_swap_usage_in_bytes(julong host_mem, julong host_swap) = 0; + virtual jlong memory_and_swap_limit_in_bytes(julong upper_mem_bound, julong upper_swap_bound) = 0; + virtual jlong memory_and_swap_usage_in_bytes(julong upper_mem_bound, julong upper_swap_bound) = 0; virtual jlong memory_soft_limit_in_bytes(julong upper_bound) = 0; virtual jlong memory_throttle_limit_in_bytes() = 0; virtual jlong memory_max_usage_in_bytes() = 0; virtual jlong rss_usage_in_bytes() = 0; virtual jlong cache_usage_in_bytes() = 0; - virtual void print_version_specific_info(outputStream* st, julong host_mem) = 0; + virtual void print_version_specific_info(outputStream* st, julong upper_mem_bound) = 0; virtual bool needs_hierarchy_adjustment() = 0; virtual bool is_read_only() = 0; virtual const char* subsystem_path() = 0; @@ -251,7 +251,7 @@ class CgroupMemoryController: public CHeapObj { class CgroupSubsystem: public CHeapObj { public: - jlong memory_limit_in_bytes(); + jlong memory_limit_in_bytes(julong upper_bound); int active_processor_count(); virtual jlong pids_max() = 0; @@ -272,14 +272,14 @@ class CgroupSubsystem: public CHeapObj { jlong cpu_usage_in_micros(); jlong memory_usage_in_bytes(); - jlong memory_and_swap_limit_in_bytes(); - jlong memory_and_swap_usage_in_bytes(); - jlong memory_soft_limit_in_bytes(); + jlong memory_and_swap_limit_in_bytes(julong upper_mem_bound, julong upper_swap_bound); + jlong memory_and_swap_usage_in_bytes(julong upper_mem_bound, julong upper_swap_bound); + jlong memory_soft_limit_in_bytes(julong upper_bound); jlong memory_throttle_limit_in_bytes(); jlong memory_max_usage_in_bytes(); jlong rss_usage_in_bytes(); jlong cache_usage_in_bytes(); - void print_version_specific_info(outputStream* st); + void print_version_specific_info(outputStream* st, julong upper_mem_bound); }; // Utility class for storing info retrieved from /proc/cgroups, diff --git a/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp b/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp index 64cb53eda28..90f01565b84 100644 --- a/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp +++ b/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp @@ -136,35 +136,35 @@ bool CgroupV1Controller::needs_hierarchy_adjustment() { } static inline -void verbose_log(julong read_mem_limit, julong host_mem) { +void verbose_log(julong read_mem_limit, julong upper_mem_bound) { if (log_is_enabled(Debug, os, container)) { jlong mem_limit = (jlong)read_mem_limit; // account for negative values - if (mem_limit < 0 || read_mem_limit >= host_mem) { + if (mem_limit < 0 || read_mem_limit >= upper_mem_bound) { const char *reason; if (mem_limit == OSCONTAINER_ERROR) { reason = "failed"; } else if (mem_limit == -1) { reason = "unlimited"; } else { - assert(read_mem_limit >= host_mem, "Expected read value exceeding host_mem"); + assert(read_mem_limit >= upper_mem_bound, "Expected read value exceeding upper memory bound"); // Exceeding physical memory is treated as unlimited. This implementation // caps it at host_mem since Cg v1 has no value to represent 'max'. reason = "ignored"; } - log_debug(os, container)("container memory limit %s: " JLONG_FORMAT ", using host value " JLONG_FORMAT, - reason, mem_limit, host_mem); + log_debug(os, container)("container memory limit %s: " JLONG_FORMAT ", upper bound is " JLONG_FORMAT, + reason, mem_limit, upper_mem_bound); } } } -jlong CgroupV1MemoryController::read_memory_limit_in_bytes(julong phys_mem) { +jlong CgroupV1MemoryController::read_memory_limit_in_bytes(julong upper_bound) { julong memlimit; CONTAINER_READ_NUMBER_CHECKED(reader(), "/memory.limit_in_bytes", "Memory Limit", memlimit); - if (memlimit >= phys_mem) { - verbose_log(memlimit, phys_mem); + if (memlimit >= upper_bound) { + verbose_log(memlimit, upper_bound); return (jlong)-1; } else { - verbose_log(memlimit, phys_mem); + verbose_log(memlimit, upper_bound); return (jlong)memlimit; } } @@ -181,10 +181,10 @@ jlong CgroupV1MemoryController::read_memory_limit_in_bytes(julong phys_mem) { * * -1 if there isn't any limit in place (note: includes values which exceed a physical * upper bound) */ -jlong CgroupV1MemoryController::read_mem_swap(julong host_total_memsw) { +jlong CgroupV1MemoryController::read_mem_swap(julong upper_memsw_bound) { julong memswlimit; CONTAINER_READ_NUMBER_CHECKED(reader(), "/memory.memsw.limit_in_bytes", "Memory and Swap Limit", memswlimit); - if (memswlimit >= host_total_memsw) { + if (memswlimit >= upper_memsw_bound) { log_trace(os, container)("Memory and Swap Limit is: Unlimited"); return (jlong)-1; } else { @@ -192,8 +192,8 @@ jlong CgroupV1MemoryController::read_mem_swap(julong host_total_memsw) { } } -jlong CgroupV1MemoryController::memory_and_swap_limit_in_bytes(julong host_mem, julong host_swap) { - jlong memory_swap = read_mem_swap(host_mem + host_swap); +jlong CgroupV1MemoryController::memory_and_swap_limit_in_bytes(julong upper_mem_bound, julong upper_swap_bound) { + jlong memory_swap = read_mem_swap(upper_mem_bound + upper_swap_bound); if (memory_swap == -1) { return memory_swap; } @@ -202,7 +202,7 @@ jlong CgroupV1MemoryController::memory_and_swap_limit_in_bytes(julong host_mem, // supported. jlong swappiness = read_mem_swappiness(); if (swappiness == 0 || memory_swap == OSCONTAINER_ERROR) { - jlong memlimit = read_memory_limit_in_bytes(host_mem); + jlong memlimit = read_memory_limit_in_bytes(upper_mem_bound); if (memory_swap == OSCONTAINER_ERROR) { log_trace(os, container)("Memory and Swap Limit has been reset to " JLONG_FORMAT " because swap is not supported", memlimit); } else { @@ -220,9 +220,9 @@ jlong memory_swap_usage_impl(CgroupController* ctrl) { return (jlong)memory_swap_usage; } -jlong CgroupV1MemoryController::memory_and_swap_usage_in_bytes(julong phys_mem, julong host_swap) { - jlong memory_sw_limit = memory_and_swap_limit_in_bytes(phys_mem, host_swap); - jlong memory_limit = read_memory_limit_in_bytes(phys_mem); +jlong CgroupV1MemoryController::memory_and_swap_usage_in_bytes(julong upper_mem_bound, julong upper_swap_bound) { + jlong memory_sw_limit = memory_and_swap_limit_in_bytes(upper_mem_bound, upper_swap_bound); + jlong memory_limit = read_memory_limit_in_bytes(upper_mem_bound); if (memory_sw_limit > 0 && memory_limit > 0) { jlong delta_swap = memory_sw_limit - memory_limit; if (delta_swap > 0) { @@ -238,10 +238,10 @@ jlong CgroupV1MemoryController::read_mem_swappiness() { return (jlong)swappiness; } -jlong CgroupV1MemoryController::memory_soft_limit_in_bytes(julong phys_mem) { +jlong CgroupV1MemoryController::memory_soft_limit_in_bytes(julong upper_bound) { julong memsoftlimit; CONTAINER_READ_NUMBER_CHECKED(reader(), "/memory.soft_limit_in_bytes", "Memory Soft Limit", memsoftlimit); - if (memsoftlimit >= phys_mem) { + if (memsoftlimit >= upper_bound) { log_trace(os, container)("Memory Soft Limit is: Unlimited"); return (jlong)-1; } else { @@ -336,10 +336,10 @@ jlong CgroupV1MemoryController::kernel_memory_usage_in_bytes() { return (jlong)kmem_usage; } -jlong CgroupV1MemoryController::kernel_memory_limit_in_bytes(julong phys_mem) { +jlong CgroupV1MemoryController::kernel_memory_limit_in_bytes(julong upper_bound) { julong kmem_limit; CONTAINER_READ_NUMBER_CHECKED(reader(), "/memory.kmem.limit_in_bytes", "Kernel Memory Limit", kmem_limit); - if (kmem_limit >= phys_mem) { + if (kmem_limit >= upper_bound) { return (jlong)-1; } return (jlong)kmem_limit; @@ -351,9 +351,9 @@ jlong CgroupV1MemoryController::kernel_memory_max_usage_in_bytes() { return (jlong)kmem_max_usage; } -void CgroupV1MemoryController::print_version_specific_info(outputStream* st, julong phys_mem) { +void CgroupV1MemoryController::print_version_specific_info(outputStream* st, julong mem_bound) { jlong kmem_usage = kernel_memory_usage_in_bytes(); - jlong kmem_limit = kernel_memory_limit_in_bytes(phys_mem); + jlong kmem_limit = kernel_memory_limit_in_bytes(mem_bound); jlong kmem_max_usage = kernel_memory_max_usage_in_bytes(); OSContainer::print_container_helper(st, kmem_limit, "kernel_memory_limit_in_bytes"); diff --git a/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp b/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp index 33bf2ed6e55..02b2c6a9fce 100644 --- a/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp +++ b/src/hotspot/os/linux/cgroupV1Subsystem_linux.hpp @@ -79,17 +79,17 @@ class CgroupV1MemoryController final : public CgroupMemoryController { } jlong read_memory_limit_in_bytes(julong upper_bound) override; jlong memory_usage_in_bytes() override; - jlong memory_and_swap_limit_in_bytes(julong host_mem, julong host_swap) override; - jlong memory_and_swap_usage_in_bytes(julong host_mem, julong host_swap) override; + jlong memory_and_swap_limit_in_bytes(julong upper_mem_bound, julong upper_swap_bound) override; + jlong memory_and_swap_usage_in_bytes(julong upper_mem_bound, julong upper_swap_bound) override; jlong memory_soft_limit_in_bytes(julong upper_bound) override; jlong memory_throttle_limit_in_bytes() override; jlong memory_max_usage_in_bytes() override; jlong rss_usage_in_bytes() override; jlong cache_usage_in_bytes() override; jlong kernel_memory_usage_in_bytes(); - jlong kernel_memory_limit_in_bytes(julong host_mem); + jlong kernel_memory_limit_in_bytes(julong upper_bound); jlong kernel_memory_max_usage_in_bytes(); - void print_version_specific_info(outputStream* st, julong host_mem) override; + void print_version_specific_info(outputStream* st, julong upper_mem_bound) override; bool needs_hierarchy_adjustment() override { return reader()->needs_hierarchy_adjustment(); } @@ -101,7 +101,7 @@ class CgroupV1MemoryController final : public CgroupMemoryController { const char* cgroup_path() override { return reader()->cgroup_path(); } private: jlong read_mem_swappiness(); - jlong read_mem_swap(julong host_total_memsw); + jlong read_mem_swap(julong upper_memsw_bound); public: CgroupV1MemoryController(const CgroupV1Controller& reader) diff --git a/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp b/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp index 661f7e909b5..38258a1f049 100644 --- a/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp +++ b/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp @@ -181,7 +181,7 @@ jlong CgroupV2MemoryController::memory_usage_in_bytes() { return (jlong)memusage; } -jlong CgroupV2MemoryController::memory_soft_limit_in_bytes(julong phys_mem) { +jlong CgroupV2MemoryController::memory_soft_limit_in_bytes(julong upper_bound) { jlong mem_soft_limit; CONTAINER_READ_NUMBER_CHECKED_MAX(reader(), "/memory.low", "Memory Soft Limit", mem_soft_limit); return mem_soft_limit; @@ -224,19 +224,19 @@ jlong CgroupV2MemoryController::cache_usage_in_bytes() { // respectively. In order to properly report a cgroup v1 like // compound value we need to sum the two values. Setting a swap limit // without also setting a memory limit is not allowed. -jlong CgroupV2MemoryController::memory_and_swap_limit_in_bytes(julong phys_mem, - julong host_swap /* unused in cg v2 */) { +jlong CgroupV2MemoryController::memory_and_swap_limit_in_bytes(julong upper_mem_bound, + julong upper_swap_bound /* unused in cg v2 */) { jlong swap_limit; bool is_ok = reader()->read_number_handle_max("/memory.swap.max", &swap_limit); if (!is_ok) { // Some container tests rely on this trace logging to happen. log_trace(os, container)("Swap Limit failed: %d", OSCONTAINER_ERROR); // swap disabled at kernel level, treat it as no swap - return read_memory_limit_in_bytes(phys_mem); + return read_memory_limit_in_bytes(upper_mem_bound); } log_trace(os, container)("Swap Limit is: " JLONG_FORMAT, swap_limit); if (swap_limit >= 0) { - jlong memory_limit = read_memory_limit_in_bytes(phys_mem); + jlong memory_limit = read_memory_limit_in_bytes(upper_mem_bound); assert(memory_limit >= 0, "swap limit without memory limit?"); return memory_limit + swap_limit; } @@ -252,7 +252,7 @@ jlong memory_swap_current_value(CgroupV2Controller* ctrl) { return (jlong)swap_current; } -jlong CgroupV2MemoryController::memory_and_swap_usage_in_bytes(julong host_mem, julong host_swap) { +jlong CgroupV2MemoryController::memory_and_swap_usage_in_bytes(julong upper_mem_bound, julong upper_swap_bound) { jlong memory_usage = memory_usage_in_bytes(); if (memory_usage >= 0) { jlong swap_current = memory_swap_current_value(reader()); @@ -276,7 +276,7 @@ jlong memory_limit_value(CgroupV2Controller* ctrl) { * memory limit in bytes or * -1 for unlimited, OSCONTAINER_ERROR for an error */ -jlong CgroupV2MemoryController::read_memory_limit_in_bytes(julong phys_mem) { +jlong CgroupV2MemoryController::read_memory_limit_in_bytes(julong upper_bound) { jlong limit = memory_limit_value(reader()); if (log_is_enabled(Trace, os, container)) { if (limit == -1) { @@ -287,18 +287,18 @@ jlong CgroupV2MemoryController::read_memory_limit_in_bytes(julong phys_mem) { } if (log_is_enabled(Debug, os, container)) { julong read_limit = (julong)limit; // avoid signed/unsigned compare - if (limit < 0 || read_limit >= phys_mem) { + if (limit < 0 || read_limit >= upper_bound) { const char* reason; if (limit == -1) { reason = "unlimited"; } else if (limit == OSCONTAINER_ERROR) { reason = "failed"; } else { - assert(read_limit >= phys_mem, "Expected mem limit to exceed host memory"); + assert(read_limit >= upper_bound, "Expected mem limit to exceed upper memory bound"); reason = "ignored"; } - log_debug(os, container)("container memory limit %s: " JLONG_FORMAT ", using host value " JLONG_FORMAT, - reason, limit, phys_mem); + log_debug(os, container)("container memory limit %s: " JLONG_FORMAT ", upper bound is " JLONG_FORMAT, + reason, limit, upper_bound); } } return limit; @@ -327,7 +327,7 @@ bool CgroupV2Controller::needs_hierarchy_adjustment() { return strcmp(_cgroup_path, "/") != 0; } -void CgroupV2MemoryController::print_version_specific_info(outputStream* st, julong phys_mem) { +void CgroupV2MemoryController::print_version_specific_info(outputStream* st, julong upper_mem_bound) { jlong swap_current = memory_swap_current_value(reader()); jlong swap_limit = memory_swap_limit_value(reader()); diff --git a/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp b/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp index e26f37925ca..07db126ce90 100644 --- a/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp +++ b/src/hotspot/os/linux/cgroupV2Subsystem_linux.hpp @@ -115,15 +115,15 @@ class CgroupV2MemoryController final: public CgroupMemoryController { } jlong read_memory_limit_in_bytes(julong upper_bound) override; - jlong memory_and_swap_limit_in_bytes(julong host_mem, julong host_swp) override; - jlong memory_and_swap_usage_in_bytes(julong host_mem, julong host_swp) override; + jlong memory_and_swap_limit_in_bytes(julong upper_mem_bound, julong upper_swap_bound) override; + jlong memory_and_swap_usage_in_bytes(julong upper_mem_bound, julong upper_swap_bound) override; jlong memory_soft_limit_in_bytes(julong upper_bound) override; jlong memory_throttle_limit_in_bytes() override; jlong memory_usage_in_bytes() override; jlong memory_max_usage_in_bytes() override; jlong rss_usage_in_bytes() override; jlong cache_usage_in_bytes() override; - void print_version_specific_info(outputStream* st, julong host_mem) override; + void print_version_specific_info(outputStream* st, julong upper_mem_bound) override; bool is_read_only() override { return reader()->is_read_only(); } diff --git a/src/hotspot/os/linux/osContainer_linux.cpp b/src/hotspot/os/linux/osContainer_linux.cpp index 899e7535fde..561f2d4926c 100644 --- a/src/hotspot/os/linux/osContainer_linux.cpp +++ b/src/hotspot/os/linux/osContainer_linux.cpp @@ -84,8 +84,8 @@ void OSContainer::init() { // We can be in one of two cases: // 1.) On a physical Linux system without any limit // 2.) On a physical Linux system with a limit enforced by other means (like systemd slice) - any_mem_cpu_limit_present = cgroup_subsystem->memory_limit_in_bytes() > 0 || - os::Linux::active_processor_count() != cgroup_subsystem->active_processor_count(); + any_mem_cpu_limit_present = memory_limit_in_bytes() > 0 || + os::Linux::active_processor_count() != active_processor_count(); if (any_mem_cpu_limit_present) { reason = " because either a cpu or a memory limit is present"; } else { @@ -103,24 +103,47 @@ const char * OSContainer::container_type() { return cgroup_subsystem->container_type(); } +bool OSContainer::available_memory_in_container(julong& value) { + jlong mem_limit = memory_limit_in_bytes(); + jlong mem_usage = memory_usage_in_bytes(); + + if (mem_limit > 0 && mem_usage <= 0) { + log_debug(os, container)("container memory usage failed: " JLONG_FORMAT, mem_usage); + } + + if (mem_limit <= 0 || mem_usage <= 0) { + return false; + } + + value = mem_limit > mem_usage ? static_cast(mem_limit - mem_usage) : 0; + + return true; +} + jlong OSContainer::memory_limit_in_bytes() { assert(cgroup_subsystem != nullptr, "cgroup subsystem not available"); - return cgroup_subsystem->memory_limit_in_bytes(); + julong phys_mem = static_cast(os::Linux::physical_memory()); + return cgroup_subsystem->memory_limit_in_bytes(phys_mem); } jlong OSContainer::memory_and_swap_limit_in_bytes() { assert(cgroup_subsystem != nullptr, "cgroup subsystem not available"); - return cgroup_subsystem->memory_and_swap_limit_in_bytes(); + julong phys_mem = static_cast(os::Linux::physical_memory()); + julong host_swap = os::Linux::host_swap(); + return cgroup_subsystem->memory_and_swap_limit_in_bytes(phys_mem, host_swap); } jlong OSContainer::memory_and_swap_usage_in_bytes() { assert(cgroup_subsystem != nullptr, "cgroup subsystem not available"); - return cgroup_subsystem->memory_and_swap_usage_in_bytes(); + julong phys_mem = static_cast(os::Linux::physical_memory()); + julong host_swap = os::Linux::host_swap(); + return cgroup_subsystem->memory_and_swap_usage_in_bytes(phys_mem, host_swap); } jlong OSContainer::memory_soft_limit_in_bytes() { assert(cgroup_subsystem != nullptr, "cgroup subsystem not available"); - return cgroup_subsystem->memory_soft_limit_in_bytes(); + julong phys_mem = static_cast(os::Linux::physical_memory()); + return cgroup_subsystem->memory_soft_limit_in_bytes(phys_mem); } jlong OSContainer::memory_throttle_limit_in_bytes() { @@ -150,7 +173,8 @@ jlong OSContainer::cache_usage_in_bytes() { void OSContainer::print_version_specific_info(outputStream* st) { assert(cgroup_subsystem != nullptr, "cgroup subsystem not available"); - cgroup_subsystem->print_version_specific_info(st); + julong phys_mem = static_cast(os::Linux::physical_memory()); + cgroup_subsystem->print_version_specific_info(st, phys_mem); } char * OSContainer::cpu_cpuset_cpus() { diff --git a/src/hotspot/os/linux/osContainer_linux.hpp b/src/hotspot/os/linux/osContainer_linux.hpp index d9b024dbbb5..6258714c48b 100644 --- a/src/hotspot/os/linux/osContainer_linux.hpp +++ b/src/hotspot/os/linux/osContainer_linux.hpp @@ -50,6 +50,7 @@ class OSContainer: AllStatic { static inline bool is_containerized(); static const char * container_type(); + static bool available_memory_in_container(julong& value); static jlong memory_limit_in_bytes(); static jlong memory_and_swap_limit_in_bytes(); static jlong memory_and_swap_usage_in_bytes(); diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 7159b2a78c4..772b170d11c 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -213,33 +213,20 @@ static bool suppress_primordial_thread_resolution = false; // utility functions -julong os::Linux::available_memory_in_container() { - julong avail_mem = static_cast(-1L); - if (OSContainer::is_containerized()) { - jlong mem_limit = OSContainer::memory_limit_in_bytes(); - jlong mem_usage; - if (mem_limit > 0 && (mem_usage = OSContainer::memory_usage_in_bytes()) < 1) { - log_debug(os, container)("container memory usage failed: " JLONG_FORMAT ", using host value", mem_usage); - } - if (mem_limit > 0 && mem_usage > 0) { - avail_mem = mem_limit > mem_usage ? (julong)mem_limit - (julong)mem_usage : 0; - } - } - return avail_mem; -} - bool os::available_memory(physical_memory_size_type& value) { - return Linux::available_memory(value); -} - -bool os::Linux::available_memory(physical_memory_size_type& value) { - julong avail_mem = available_memory_in_container(); - if (avail_mem != static_cast(-1L)) { + julong avail_mem = 0; + if (OSContainer::is_containerized() && OSContainer::available_memory_in_container(avail_mem)) { log_trace(os)("available container memory: " JULONG_FORMAT, avail_mem); value = static_cast(avail_mem); return true; } + return Linux::available_memory(value); +} + +bool os::Linux::available_memory(physical_memory_size_type& value) { + julong avail_mem = static_cast(-1L); + FILE *fp = os::fopen("/proc/meminfo", "r"); if (fp != nullptr) { char buf[80]; @@ -264,24 +251,25 @@ bool os::Linux::available_memory(physical_memory_size_type& value) { } bool os::free_memory(physical_memory_size_type& value) { + julong free_mem = 0; + if (OSContainer::is_containerized() && OSContainer::available_memory_in_container(free_mem)) { + log_trace(os)("free container memory: " JULONG_FORMAT, free_mem); + value = static_cast(free_mem); + return true; + } + return Linux::free_memory(value); } bool os::Linux::free_memory(physical_memory_size_type& value) { // values in struct sysinfo are "unsigned long" struct sysinfo si; - julong free_mem = available_memory_in_container(); - if (free_mem != static_cast(-1L)) { - log_trace(os)("free container memory: " JULONG_FORMAT, free_mem); - value = static_cast(free_mem); - return true; - } int ret = sysinfo(&si); if (ret != 0) { return false; } - free_mem = (julong)si.freeram * si.mem_unit; + julong free_mem = (julong)si.freeram * si.mem_unit; log_trace(os)("free memory: " JULONG_FORMAT, free_mem); value = static_cast(free_mem); return true; From 7ad9bdef1ed250a824ee9dee69b37bbcc8f7c924 Mon Sep 17 00:00:00 2001 From: Daniel Fuchs Date: Thu, 2 Oct 2025 15:19:26 +0000 Subject: [PATCH 0038/1639] 8368630: java/net/httpclient/http3/H3ServerPushTest.java succeeds but fails in jtreg timeout Reviewed-by: syan, jpai --- test/jdk/java/net/httpclient/http3/H3ServerPushTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/jdk/java/net/httpclient/http3/H3ServerPushTest.java b/test/jdk/java/net/httpclient/http3/H3ServerPushTest.java index 9b4858f50c9..ed5a14d8576 100644 --- a/test/jdk/java/net/httpclient/http3/H3ServerPushTest.java +++ b/test/jdk/java/net/httpclient/http3/H3ServerPushTest.java @@ -78,7 +78,7 @@ import static org.junit.jupiter.api.Assertions.fail; * /test/lib * @build jdk.httpclient.test.lib.http2.Http2TestServer * jdk.test.lib.net.SimpleSSLContext - * @run junit H3ServerPushTest + * @run junit/othervm/timeout=240 H3ServerPushTest */ /** From 1a03a1fbb1c7a83469128106341591c59428437a Mon Sep 17 00:00:00 2001 From: Igor Veresov Date: Thu, 2 Oct 2025 15:38:51 +0000 Subject: [PATCH 0039/1639] 8369033: Remove dead code in training data Reviewed-by: rcastanedalo, kvn --- src/hotspot/share/oops/trainingData.cpp | 17 ++++------------- src/hotspot/share/oops/trainingData.hpp | 15 +++++---------- 2 files changed, 9 insertions(+), 23 deletions(-) diff --git a/src/hotspot/share/oops/trainingData.cpp b/src/hotspot/share/oops/trainingData.cpp index ca5883a19ca..dcf95cf4653 100644 --- a/src/hotspot/share/oops/trainingData.cpp +++ b/src/hotspot/share/oops/trainingData.cpp @@ -25,7 +25,6 @@ #include "cds/cdsConfig.hpp" #include "ci/ciEnv.hpp" #include "ci/ciMetadata.hpp" -#include "classfile/classLoaderData.hpp" #include "classfile/compactHashtable.hpp" #include "classfile/javaClasses.hpp" #include "classfile/symbolTable.hpp" @@ -312,7 +311,6 @@ void CompileTrainingData::notice_jit_observation(ciEnv* env, ciBaseObject* what) CompileTask* task = env->task(); assert(task != nullptr, ""); Method* method = task->method(); - InstanceKlass* compiling_klass = method->method_holder(); if (what->is_metadata()) { ciMetadata* md = what->as_metadata(); if (md->is_loaded() && md->is_instance_klass()) { @@ -341,13 +339,7 @@ void KlassTrainingData::prepare(Visitor& visitor) { return; } visitor.visit(this); - ClassLoaderData* loader_data = nullptr; - if (_holder != nullptr) { - loader_data = _holder->class_loader_data(); - } else { - loader_data = java_lang_ClassLoader::loader_data(SystemDictionary::java_system_loader()); // default CLD - } - _comp_deps.prepare(loader_data); + _comp_deps.prepare(); } void MethodTrainingData::prepare(Visitor& visitor) { @@ -375,9 +367,8 @@ void CompileTrainingData::prepare(Visitor& visitor) { } visitor.visit(this); method()->prepare(visitor); - ClassLoaderData* loader_data = _method->klass()->class_loader_data(); - _init_deps.prepare(loader_data); - _ci_records.prepare(loader_data); + _init_deps.prepare(); + _ci_records.prepare(); } KlassTrainingData* KlassTrainingData::make(InstanceKlass* holder, bool null_if_not_found) { @@ -769,7 +760,7 @@ void CompileTrainingData::metaspace_pointers_do(MetaspaceClosure* iter) { } template -void TrainingData::DepList::prepare(ClassLoaderData* loader_data) { +void TrainingData::DepList::prepare() { if (_deps == nullptr && _deps_dyn != nullptr) { int len = _deps_dyn->length(); _deps = MetadataFactory::new_array_from_c_heap(len, mtClassShared); diff --git a/src/hotspot/share/oops/trainingData.hpp b/src/hotspot/share/oops/trainingData.hpp index d214a03a284..fbecb5c46bf 100644 --- a/src/hotspot/share/oops/trainingData.hpp +++ b/src/hotspot/share/oops/trainingData.hpp @@ -26,7 +26,6 @@ #define SHARE_OOPS_TRAININGDATA_HPP #include "cds/cdsConfig.hpp" -#include "classfile/classLoaderData.hpp" #include "classfile/compactHashtable.hpp" #include "compiler/compiler_globals.hpp" #include "compiler/compilerDefinitions.hpp" @@ -402,7 +401,7 @@ private: _deps_dyn = nullptr; } #endif - void prepare(ClassLoaderData* loader_data); + void prepare(); void metaspace_pointers_do(MetaspaceClosure *iter); }; @@ -479,10 +478,6 @@ class KlassTrainingData : public TrainingData { } virtual KlassTrainingData* as_KlassTrainingData() const { return const_cast(this); }; - ClassLoaderData* class_loader_data() { - assert(has_holder(), ""); - return holder()->class_loader_data(); - } void notice_fully_initialized() NOT_CDS_RETURN; void print_on(outputStream* st, bool name_only) const; @@ -620,8 +615,8 @@ public: #if INCLUDE_CDS void remove_unshareable_info() { _data.remove_unshareable_info(); } #endif - void prepare(ClassLoaderData* loader_data) { - _data.prepare(loader_data); + void prepare() { + _data.prepare(); } void metaspace_pointers_do(MetaspaceClosure *iter) { _data.metaspace_pointers_do(iter); @@ -639,8 +634,8 @@ public: ciMethod__inline_instructions_size.remove_unshareable_info(); } #endif - void prepare(ClassLoaderData* loader_data) { - ciMethod__inline_instructions_size.prepare(loader_data); + void prepare() { + ciMethod__inline_instructions_size.prepare(); } void metaspace_pointers_do(MetaspaceClosure *iter) { ciMethod__inline_instructions_size.metaspace_pointers_do(iter); From 5fccabff15ae8bcc3d03156fa331bbc0fefb0cbe Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Thu, 2 Oct 2025 15:51:46 +0000 Subject: [PATCH 0040/1639] 8368670: Deadlock in JFR on event register + class load Reviewed-by: mgronlun --- .../share/classes/jdk/jfr/internal/MetadataRepository.java | 2 +- src/jdk.jfr/share/classes/jdk/jfr/internal/SettingsManager.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java index e574ab47992..22d55e6e99f 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/MetadataRepository.java @@ -291,7 +291,7 @@ public final class MetadataRepository { } } - synchronized boolean isEnabled(String eventName) { + boolean isEnabled(String eventName) { return settingsManager.isEnabled(eventName); } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/SettingsManager.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/SettingsManager.java index 84caf7cb460..bd8fa078dc8 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/SettingsManager.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/SettingsManager.java @@ -129,7 +129,7 @@ final class SettingsManager { } } - private Map availableSettings = new LinkedHashMap<>(); + private volatile Map availableSettings = new LinkedHashMap<>(); void setSettings(List> activeSettings, boolean writeSettingEvents) { // store settings so they are available if a new event class is loaded From 3d113af9e33ddf3d80452cb72f1b47b4936ec6a0 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Thu, 2 Oct 2025 16:43:01 +0000 Subject: [PATCH 0041/1639] 8369051: More small Float16 refactorings Reviewed-by: rgiulietti --- .../share/classes/jdk/incubator/vector/Float16.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16.java index b75adf350b6..a564cdfed0f 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16.java @@ -34,6 +34,7 @@ import java.math.BigInteger; import static jdk.incubator.vector.Float16Consts.SIGN_BIT_MASK; import static jdk.incubator.vector.Float16Consts.EXP_BIT_MASK; import static jdk.incubator.vector.Float16Consts.SIGNIF_BIT_MASK; +import static jdk.incubator.vector.Float16Consts.MAG_BIT_MASK; import static java.lang.Float.float16ToFloat; import static java.lang.Float.floatToFloat16; @@ -396,7 +397,7 @@ public final class Float16 } long f_signif_bits = doppel & 0x000f_ffff_ffff_ffffL | msb; - int PRECISION_DIFF = Double.PRECISION - PRECISION; // 42 + final int PRECISION_DIFF = Double.PRECISION - PRECISION; // 42 // Significand bits as if using rounding to zero (truncation). short signif_bits = (short)(f_signif_bits >> (PRECISION_DIFF + expdelta)); @@ -774,7 +775,7 @@ public final class Float16 * @see Double#isFinite(double) */ public static boolean isFinite(Float16 f16) { - return (float16ToRawShortBits(f16) & (EXP_BIT_MASK | SIGNIF_BIT_MASK)) <= + return (float16ToRawShortBits(f16) & MAG_BIT_MASK) <= float16ToRawShortBits(MAX_VALUE); } @@ -1093,7 +1094,7 @@ public final class Float16 * 2) performing the operation in the wider format * 3) converting the result from 2) to the narrower format * - * For example, this property hold between the formats used for the + * For example, this property holds between the formats used for the * float and double types. Therefore, the following is a valid * implementation of a float addition: * @@ -1477,7 +1478,7 @@ public final class Float16 // operation. Therefore, in this case do _not_ use the float // unary minus as an implementation as that is not guaranteed // to flip the sign bit of a NaN. - return shortBitsToFloat16((short)(f16.value ^ (short)0x0000_8000)); + return shortBitsToFloat16((short)(f16.value ^ SIGN_BIT_MASK)); } /** @@ -1495,7 +1496,7 @@ public final class Float16 public static Float16 abs(Float16 f16) { // Zero out sign bit. Per IEE 754-2019 section 5.5.1, abs is a // bit-level operation and not a logical operation. - return shortBitsToFloat16((short)(f16.value & (short)0x0000_7FFF)); + return shortBitsToFloat16((short)(f16.value & MAG_BIT_MASK)); } /** From 1d55adee11fc2fdbf2e009e1308b763fd7217dad Mon Sep 17 00:00:00 2001 From: Francesco Andreuzzi Date: Thu, 2 Oct 2025 18:49:00 +0000 Subject: [PATCH 0042/1639] 8368989: Use NMethodMarkingScope and ThreadsClaimTokenScope in shenandoahSTWMark Reviewed-by: shade, ayang --- src/hotspot/share/gc/shenandoah/shenandoahSTWMark.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahSTWMark.cpp b/src/hotspot/share/gc/shenandoah/shenandoahSTWMark.cpp index 260c1e0276f..53391a3e224 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahSTWMark.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahSTWMark.cpp @@ -24,8 +24,7 @@ */ - -#include "gc/shared/strongRootsScope.hpp" +#include "code/nmethod.hpp" #include "gc/shared/taskTerminator.hpp" #include "gc/shared/workerThread.hpp" #include "gc/shenandoah/shenandoahClosures.inline.hpp" @@ -36,10 +35,13 @@ #include "gc/shenandoah/shenandoahRootProcessor.inline.hpp" #include "gc/shenandoah/shenandoahSTWMark.hpp" #include "gc/shenandoah/shenandoahVerifier.hpp" +#include "runtime/threads.hpp" class ShenandoahSTWMarkTask : public WorkerTask { private: ShenandoahSTWMark* const _mark; + NMethodMarkingScope _nmethod_marking_scope; + ThreadsClaimTokenScope _threads_claim_token_scope; public: ShenandoahSTWMarkTask(ShenandoahSTWMark* mark); @@ -48,7 +50,9 @@ public: ShenandoahSTWMarkTask::ShenandoahSTWMarkTask(ShenandoahSTWMark* mark) : WorkerTask("Shenandoah STW mark"), - _mark(mark) { + _mark(mark), + _nmethod_marking_scope(), + _threads_claim_token_scope() { } void ShenandoahSTWMarkTask::work(uint worker_id) { @@ -98,7 +102,6 @@ void ShenandoahSTWMark::mark() { _generation->scan_remembered_set(false /* is_concurrent */); } - StrongRootsScope scope(nworkers); ShenandoahSTWMarkTask task(this); heap->workers()->run_task(&task); From 3f27a03bba4760694a276376d08fb1ba97d08f7e Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Thu, 2 Oct 2025 20:00:58 +0000 Subject: [PATCH 0043/1639] 8368727: CDS custom loader support causes asserts during class unloading Reviewed-by: coleenp, dholmes --- .../classfile/systemDictionaryShared.cpp | 1 - src/hotspot/share/oops/klass.cpp | 7 ++- .../UnloadUnregisteredLoaderTest.java | 18 ++++++-- .../test-classes/CustomLoadee5.java | 2 +- .../UnloadUnregisteredLoader.java | 45 ++++++++++++++++++- 5 files changed, 61 insertions(+), 12 deletions(-) diff --git a/src/hotspot/share/classfile/systemDictionaryShared.cpp b/src/hotspot/share/classfile/systemDictionaryShared.cpp index da022436292..b092e71f4e7 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.cpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp @@ -174,7 +174,6 @@ InstanceKlass* SystemDictionaryShared::acquire_class_for_current_thread( // No longer holding SharedDictionary_lock // No need to lock, as can be held only by a single thread. - loader_data->add_class(ik); // Get the package entry. PackageEntry* pkg_entry = CDSProtectionDomain::get_package_entry_from_class(ik, class_loader); diff --git a/src/hotspot/share/oops/klass.cpp b/src/hotspot/share/oops/klass.cpp index b3386694b79..208a274d766 100644 --- a/src/hotspot/share/oops/klass.cpp +++ b/src/hotspot/share/oops/klass.cpp @@ -872,11 +872,10 @@ void Klass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protec // modify the CLD list outside a safepoint. if (class_loader_data() == nullptr) { set_class_loader_data(loader_data); - - // Add to class loader list first before creating the mirror - // (same order as class file parsing) - loader_data->add_class(this); } + // Add to class loader list first before creating the mirror + // (same order as class file parsing) + loader_data->add_class(this); Handle loader(THREAD, loader_data->class_loader()); ModuleEntry* module_entry = nullptr; diff --git a/test/hotspot/jtreg/runtime/cds/appcds/customLoader/UnloadUnregisteredLoaderTest.java b/test/hotspot/jtreg/runtime/cds/appcds/customLoader/UnloadUnregisteredLoaderTest.java index b7f472f5c0e..db26c6cbd18 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/customLoader/UnloadUnregisteredLoaderTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/customLoader/UnloadUnregisteredLoaderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,9 +29,10 @@ * @requires vm.cds * @requires vm.cds.custom.loaders * @requires vm.opt.final.ClassUnloading - * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds + * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds /test/hotspot/jtreg/runtime/cds/appcds/test-classes * @build jdk.test.whitebox.WhiteBox jdk.test.lib.classloader.ClassUnloadCommon * @compile test-classes/UnloadUnregisteredLoader.java test-classes/CustomLoadee.java + * test-classes/CustomLoadee5.java test-classes/CustomLoadee5Child.java * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * jdk.test.lib.classloader.ClassUnloadCommon * jdk.test.lib.classloader.ClassUnloadCommon$1 @@ -49,12 +50,19 @@ public class UnloadUnregisteredLoaderTest { CDSOptions.disableRuntimePrefixForEpsilonGC(); } public static void main(String[] args) throws Exception { - String appJar1 = JarBuilder.build("UnloadUnregisteredLoader_app1", "UnloadUnregisteredLoader"); + String appJar1 = JarBuilder.build("UnloadUnregisteredLoader_app1", + "UnloadUnregisteredLoader", + "UnloadUnregisteredLoader$CustomLoader", + "CustomLoadee5", + "Util"); String appJar2 = JarBuilder.build(true, "UnloadUnregisteredLoader_app2", "jdk/test/lib/classloader/ClassUnloadCommon", "jdk/test/lib/classloader/ClassUnloadCommon$1", "jdk/test/lib/classloader/ClassUnloadCommon$TestFailure"); - String customJarPath = JarBuilder.build("UnloadUnregisteredLoader_custom", "CustomLoadee"); + String customJarPath = JarBuilder.build("UnloadUnregisteredLoader_custom", + "CustomLoadee", + "CustomLoadee5", + "CustomLoadee5Child"); String wbJar = JarBuilder.build(true, "WhiteBox", "jdk/test/whitebox/WhiteBox"); String use_whitebox_jar = "-Xbootclasspath/a:" + wbJar; @@ -66,6 +74,8 @@ public class UnloadUnregisteredLoaderTest { "jdk/test/lib/classloader/ClassUnloadCommon$TestFailure", "java/lang/Object id: 1", "CustomLoadee id: 2 super: 1 source: " + customJarPath, + "CustomLoadee5 id: 3 super: 1 source: " + customJarPath, + "CustomLoadee5Child id: 4 super: 3 source: " + customJarPath, }; OutputAnalyzer output; diff --git a/test/hotspot/jtreg/runtime/cds/appcds/customLoader/test-classes/CustomLoadee5.java b/test/hotspot/jtreg/runtime/cds/appcds/customLoader/test-classes/CustomLoadee5.java index f3cda51c9fa..ba9f6dafa95 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/customLoader/test-classes/CustomLoadee5.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/customLoader/test-classes/CustomLoadee5.java @@ -21,7 +21,7 @@ * questions. */ -class CustomLoadee5 { +public class CustomLoadee5 { public String toString() { return "this is CustomLoadee5"; } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/customLoader/test-classes/UnloadUnregisteredLoader.java b/test/hotspot/jtreg/runtime/cds/appcds/customLoader/test-classes/UnloadUnregisteredLoader.java index 0e0e814327e..e6bd7407466 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/customLoader/test-classes/UnloadUnregisteredLoader.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/customLoader/test-classes/UnloadUnregisteredLoader.java @@ -23,6 +23,7 @@ */ import java.io.File; +import java.io.InputStream; import java.net.URL; import java.net.URLClassLoader; import jdk.test.whitebox.WhiteBox; @@ -46,9 +47,11 @@ public class UnloadUnregisteredLoader { } } - public static void doit(URL urls[], String className, boolean isFirstTime) throws Exception { + public static void doit(URL urls[], String className, boolean isFirstTime) throws Exception { ClassLoader appLoader = UnloadUnregisteredLoader.class.getClassLoader(); - URLClassLoader custLoader = new URLClassLoader(urls, appLoader); + CustomLoader custLoader = new CustomLoader(urls, appLoader); + + // Part 1 -- load CustomLoadee. It should be loaded from archive when isFirstTime==true Class klass = custLoader.loadClass(className); WhiteBox wb = WhiteBox.getWhiteBox(); @@ -68,5 +71,43 @@ public class UnloadUnregisteredLoader { } } } + + // Part 2 + // + // CustomLoadee5 is never loaded from the archive, because the classfile bytes don't match + // CustomLoadee5Child is never loaded from the archive, its super is not loaded from the archive + try (InputStream in = appLoader.getResourceAsStream("CustomLoadee5.class")) { + byte[] b = in.readAllBytes(); + Util.replace(b, "this is", "DAS IST"); // Modify the bytecodes + Class c = custLoader.myDefineClass(b, 0, b.length); + System.out.println(c.newInstance()); + if (!"DAS IST CustomLoadee5".equals(c.newInstance().toString())) { + throw new RuntimeException("Bytecode modification not successful"); + } + if (wb.isSharedClass(c)) { + throw new RuntimeException(c + "should not be loaded from CDS"); + } + } + + // When isFirstTime==true, the VM will try to load the archived copy of CustomLoadee5Child, + // but it will fail (because CustomLoadee5 was not loaded from the archive) and will recover + // by decoding the class from its classfile data. + // This failure should not leave the JVM in an inconsistent state. + Class child = custLoader.loadClass("CustomLoadee5Child"); + if (wb.isSharedClass(child)) { + throw new RuntimeException(child + "should not be loaded from CDS"); + } + } + + static class CustomLoader extends URLClassLoader { + public CustomLoader(URL[] urls, ClassLoader parent) { + super(urls, parent); + } + + public Class myDefineClass(byte[] b, int off, int len) + throws ClassFormatError + { + return super.defineClass(b, off, len); + } } } From fa6e884105ac247b3b83a5a2329f9c18888bd7d0 Mon Sep 17 00:00:00 2001 From: Damon Nguyen Date: Thu, 2 Oct 2025 22:09:14 +0000 Subject: [PATCH 0044/1639] 8298823: [macos] java/awt/Mouse/EnterExitEvents/DragWindowTest.java continues to fail with "No MouseReleased event on label!" Reviewed-by: aivanov, azvegint --- test/jdk/ProblemList.txt | 1 - .../Mouse/EnterExitEvents/DragWindowTest.java | 115 +++++++----------- 2 files changed, 46 insertions(+), 70 deletions(-) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 1602baa9894..8d13670805f 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -188,7 +188,6 @@ java/awt/Mixing/AWT_Mixing/JTextFieldOverlapping.java 8158801 windows-all java/awt/Mixing/AWT_Mixing/JToggleButtonInGlassPaneOverlapping.java 8158801 windows-all java/awt/Mixing/AWT_Mixing/JToggleButtonOverlapping.java 8158801 windows-all java/awt/Mixing/NonOpaqueInternalFrame.java 7124549 macosx-all -java/awt/Mouse/EnterExitEvents/DragWindowTest.java 8298823 macosx-all java/awt/Focus/ActualFocusedWindowTest/ActualFocusedWindowRetaining.java 6829264 generic-all java/awt/datatransfer/DragImage/MultiResolutionDragImageTest.java 8080982 generic-all java/awt/datatransfer/SystemFlavorMap/AddFlavorTest.java 8079268 linux-all diff --git a/test/jdk/java/awt/Mouse/EnterExitEvents/DragWindowTest.java b/test/jdk/java/awt/Mouse/EnterExitEvents/DragWindowTest.java index 4f789668c4a..2a77f294298 100644 --- a/test/jdk/java/awt/Mouse/EnterExitEvents/DragWindowTest.java +++ b/test/jdk/java/awt/Mouse/EnterExitEvents/DragWindowTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,11 +26,8 @@ * @key headful * @bug 7154048 * @summary Window created under a mouse does not receive mouse enter event. - * Mouse Entered/Exited events are wrongly generated during dragging the window - * from one component to another - * @library ../../regtesthelpers - * @build Util - * @author alexandr.scherbatiy area=awt.event + * Mouse Entered/Exited events are wrongly generated during dragging the + * window from one component to another * @run main DragWindowTest */ @@ -50,76 +47,67 @@ import javax.swing.JButton; import javax.swing.JPanel; import javax.swing.SwingUtilities; -import java.util.concurrent.Callable; - -import test.java.awt.regtesthelpers.Util; - public class DragWindowTest { - private static volatile int dragWindowMouseEnteredCount = 0; - private static volatile int dragWindowMouseReleasedCount = 0; private static volatile int buttonMouseEnteredCount = 0; private static volatile int labelMouseReleasedCount = 0; + + private static volatile Point pointToClick; + private static volatile Point pointToDrag; + private static MyDragWindow dragWindow; private static JLabel label; private static JButton button; + private static JFrame frame; public static void main(String[] args) throws Exception { + try { + Robot robot = new Robot(); + robot.setAutoDelay(100); - Robot robot = new Robot(); - robot.setAutoDelay(100); + SwingUtilities.invokeAndWait(DragWindowTest::createAndShowGUI); - SwingUtilities.invokeAndWait(new Runnable() { + robot.delay(250); + robot.waitForIdle(); - @Override - public void run() { - createAndShowGUI(); + SwingUtilities.invokeAndWait(() -> { + pointToClick = getCenterPoint(label); + pointToDrag = getCenterPoint(button); + }); + + robot.mouseMove(pointToClick.x, pointToClick.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + robot.delay(250); + + if (dragWindowMouseEnteredCount != 1) { + throw new RuntimeException("No MouseEntered event on Drag Window!"); } - }); - robot.delay(250); - robot.waitForIdle(); + // Reset entered count to check if mouse entered starting from here + buttonMouseEnteredCount = 0; + robot.mouseMove(pointToDrag.x, pointToDrag.y); + robot.waitForIdle(); + robot.delay(250); - Point pointToClick = Util.invokeOnEDT(new Callable() { - - @Override - public Point call() throws Exception { - return getCenterPoint(label); + if (buttonMouseEnteredCount != 0) { + throw new RuntimeException("Extra MouseEntered event on button!"); } - }); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + robot.delay(250); - robot.mouseMove(pointToClick.x, pointToClick.y); - robot.mousePress(InputEvent.BUTTON1_MASK); - robot.waitForIdle(); - - if (dragWindowMouseEnteredCount != 1) { - throw new RuntimeException("No MouseEntered event on Drag Window!"); - } - - Point pointToDrag = Util.invokeOnEDT(new Callable() { - - @Override - public Point call() throws Exception { - button.addMouseListener(new ButtonMouseListener()); - return getCenterPoint(button); + if (labelMouseReleasedCount != 1) { + throw new RuntimeException("No MouseReleased event on label!"); } - }); - - robot.mouseMove(pointToDrag.x, pointToDrag.y); - robot.waitForIdle(); - - if (buttonMouseEnteredCount != 0) { - throw new RuntimeException("Extra MouseEntered event on button!"); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); } - - robot.mouseRelease(InputEvent.BUTTON1_MASK); - robot.waitForIdle(); - - if (labelMouseReleasedCount != 1) { - throw new RuntimeException("No MouseReleased event on label!"); - } - } private static Point getCenterPoint(Component comp) { @@ -129,8 +117,7 @@ public class DragWindowTest { } private static void createAndShowGUI() { - - JFrame frame = new JFrame("Main Frame"); + frame = new JFrame("DragWindowTest"); frame.setSize(300, 200); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); @@ -142,6 +129,7 @@ public class DragWindowTest { button = new JButton("Button"); Panel panel = new Panel(new BorderLayout()); + button.addMouseListener(new ButtonMouseListener()); panel.add(label, BorderLayout.NORTH); panel.add(button, BorderLayout.CENTER); @@ -149,7 +137,6 @@ public class DragWindowTest { frame.getContentPane().add(panel); frame.setLocationRelativeTo(null); frame.setVisible(true); - } private static Point getAbsoluteLocation(MouseEvent e) { @@ -157,7 +144,6 @@ public class DragWindowTest { } static class MyDragWindow extends Window { - static int d = 30; public MyDragWindow(Window parent, Point location) { @@ -176,8 +162,6 @@ public class DragWindowTest { } static class LabelMouseListener extends MouseAdapter { - - Point origin; Window parent; public LabelMouseListener(Window parent) { @@ -210,20 +194,13 @@ public class DragWindowTest { } static class DragWindowMouseListener extends MouseAdapter { - @Override public void mouseEntered(MouseEvent e) { dragWindowMouseEnteredCount++; } - - @Override - public void mouseReleased(MouseEvent e) { - dragWindowMouseReleasedCount++; - } } static class ButtonMouseListener extends MouseAdapter { - @Override public void mouseEntered(MouseEvent e) { buttonMouseEnteredCount++; From da7121aff9eccb046b82a75093034f1cdbd9b9e4 Mon Sep 17 00:00:00 2001 From: Dean Long Date: Thu, 2 Oct 2025 22:21:13 +0000 Subject: [PATCH 0045/1639] 8366461: Remove obsolete method handle invoke logic Reviewed-by: vlivanov, mhaessig --- src/hotspot/cpu/aarch64/aarch64.ad | 4 - .../cpu/aarch64/c1_FrameMap_aarch64.cpp | 7 -- src/hotspot/cpu/aarch64/frame_aarch64.cpp | 45 +------ src/hotspot/cpu/aarch64/frame_aarch64.hpp | 9 +- .../cpu/aarch64/frame_aarch64.inline.hpp | 3 - src/hotspot/cpu/arm/arm.ad | 36 ------ src/hotspot/cpu/arm/arm_32.ad | 5 +- src/hotspot/cpu/arm/c1_FrameMap_arm.cpp | 5 - src/hotspot/cpu/arm/c1_Runtime1_arm.cpp | 12 -- src/hotspot/cpu/arm/frame_arm.cpp | 50 -------- src/hotspot/cpu/arm/frame_arm.hpp | 11 +- src/hotspot/cpu/arm/frame_arm.inline.hpp | 4 +- src/hotspot/cpu/arm/register_arm.hpp | 3 +- src/hotspot/cpu/arm/runtime_arm.cpp | 5 - src/hotspot/cpu/ppc/c1_FrameMap_ppc.cpp | 9 -- src/hotspot/cpu/ppc/ppc.ad | 5 - src/hotspot/cpu/riscv/c1_FrameMap_riscv.cpp | 5 - src/hotspot/cpu/riscv/frame_riscv.cpp | 46 +------ src/hotspot/cpu/riscv/frame_riscv.hpp | 9 +- src/hotspot/cpu/riscv/frame_riscv.inline.hpp | 5 +- src/hotspot/cpu/riscv/riscv.ad | 4 - src/hotspot/cpu/s390/c1_FrameMap_s390.cpp | 7 -- src/hotspot/cpu/s390/s390.ad | 5 - src/hotspot/cpu/x86/c1_FrameMap_x86.cpp | 7 -- src/hotspot/cpu/x86/frame_x86.cpp | 44 +------ src/hotspot/cpu/x86/frame_x86.hpp | 9 +- src/hotspot/cpu/x86/frame_x86.inline.hpp | 3 - src/hotspot/cpu/x86/x86_64.ad | 5 - src/hotspot/os/posix/signals_posix.cpp | 4 +- src/hotspot/os/windows/os_windows.cpp | 4 +- src/hotspot/share/asm/codeBuffer.hpp | 2 - src/hotspot/share/c1/c1_Compilation.cpp | 9 -- src/hotspot/share/c1/c1_Compilation.hpp | 5 - src/hotspot/share/c1/c1_FrameMap.hpp | 3 - src/hotspot/share/c1/c1_IR.cpp | 4 +- src/hotspot/share/c1/c1_IR.hpp | 8 +- src/hotspot/share/c1/c1_LIR.cpp | 5 - src/hotspot/share/c1/c1_LIR.hpp | 3 - src/hotspot/share/c1/c1_LIRAssembler.cpp | 6 - src/hotspot/share/c1/c1_LIRGenerator.cpp | 19 --- src/hotspot/share/c1/c1_Runtime1.cpp | 7 -- src/hotspot/share/code/debugInfoRec.cpp | 2 - src/hotspot/share/code/debugInfoRec.hpp | 3 +- src/hotspot/share/code/nmethod.cpp | 30 ----- src/hotspot/share/code/nmethod.hpp | 11 -- src/hotspot/share/code/nmethod.inline.hpp | 6 +- src/hotspot/share/code/pcDesc.hpp | 14 +-- .../share/jvmci/jvmciCodeInstaller.cpp | 16 +-- .../share/jvmci/jvmciCodeInstaller.hpp | 6 +- src/hotspot/share/jvmci/jvmciRuntime.cpp | 8 -- src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 1 - src/hotspot/share/opto/callGenerator.cpp | 4 - src/hotspot/share/opto/callnode.hpp | 4 - src/hotspot/share/opto/compile.cpp | 2 - src/hotspot/share/opto/compile.hpp | 6 - src/hotspot/share/opto/lcm.cpp | 11 -- src/hotspot/share/opto/machnode.cpp | 7 +- src/hotspot/share/opto/machnode.hpp | 1 - src/hotspot/share/opto/matcher.cpp | 115 ++---------------- src/hotspot/share/opto/matcher.hpp | 7 +- src/hotspot/share/opto/output.cpp | 17 --- src/hotspot/share/opto/runtime.cpp | 3 - src/hotspot/share/runtime/deoptimization.cpp | 7 +- src/hotspot/share/runtime/frame.cpp | 9 +- src/hotspot/share/runtime/frame.inline.hpp | 7 +- src/hotspot/share/runtime/javaThread.cpp | 1 - src/hotspot/share/runtime/javaThread.hpp | 3 - src/hotspot/share/runtime/sharedRuntime.cpp | 5 - src/hotspot/share/runtime/vmStructs.cpp | 3 - .../classes/sun/jvm/hotspot/code/NMethod.java | 18 +-- .../classes/sun/jvm/hotspot/code/PCDesc.java | 9 +- .../sun/jvm/hotspot/runtime/Frame.java | 20 ++- .../hotspot/runtime/aarch64/AARCH64Frame.java | 42 +------ .../jvm/hotspot/runtime/ppc64/PPC64Frame.java | 29 +---- .../hotspot/runtime/riscv64/RISCV64Frame.java | 42 +------ .../sun/jvm/hotspot/runtime/x86/X86Frame.java | 41 +------ 76 files changed, 74 insertions(+), 877 deletions(-) diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index e0459716122..51cdf8c71df 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -2568,10 +2568,6 @@ RegMask Matcher::modL_proj_mask() { return RegMask(); } -const RegMask Matcher::method_handle_invoke_SP_save_mask() { - return FP_REG_mask(); -} - bool size_fits_all_mem_uses(AddPNode* addp, int shift) { for (DUIterator_Fast imax, i = addp->fast_outs(imax); i < imax; i++) { Node* u = addp->fast_out(i); diff --git a/src/hotspot/cpu/aarch64/c1_FrameMap_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_FrameMap_aarch64.cpp index 9d30092b45a..83d0952dcb4 100644 --- a/src/hotspot/cpu/aarch64/c1_FrameMap_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c1_FrameMap_aarch64.cpp @@ -383,13 +383,6 @@ LIR_Opr FrameMap::stack_pointer() { return FrameMap::sp_opr; } - -// JSR 292 -LIR_Opr FrameMap::method_handle_invoke_SP_save_opr() { - return LIR_OprFact::illegalOpr; // Not needed on aarch64 -} - - bool FrameMap::validate_frame() { return true; } diff --git a/src/hotspot/cpu/aarch64/frame_aarch64.cpp b/src/hotspot/cpu/aarch64/frame_aarch64.cpp index aff50b9cf2f..bdbef53bfdb 100644 --- a/src/hotspot/cpu/aarch64/frame_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/frame_aarch64.cpp @@ -228,8 +228,7 @@ bool frame::safe_for_sender(JavaThread *thread) { nmethod* nm = sender_blob->as_nmethod_or_null(); if (nm != nullptr) { - if (nm->is_deopt_mh_entry(sender_pc) || nm->is_deopt_entry(sender_pc) || - nm->method()->is_method_handle_intrinsic()) { + if (nm->is_deopt_entry(sender_pc) || nm->method()->is_method_handle_intrinsic()) { return false; } } @@ -454,48 +453,6 @@ JavaThread** frame::saved_thread_address(const frame& f) { return thread_addr; } -//------------------------------------------------------------------------------ -// frame::verify_deopt_original_pc -// -// Verifies the calculated original PC of a deoptimization PC for the -// given unextended SP. -#ifdef ASSERT -void frame::verify_deopt_original_pc(nmethod* nm, intptr_t* unextended_sp) { - frame fr; - - // This is ugly but it's better than to change {get,set}_original_pc - // to take an SP value as argument. And it's only a debugging - // method anyway. - fr._unextended_sp = unextended_sp; - - address original_pc = nm->get_original_pc(&fr); - assert(nm->insts_contains_inclusive(original_pc), - "original PC must be in the main code section of the compiled method (or must be immediately following it)"); -} -#endif - -//------------------------------------------------------------------------------ -// frame::adjust_unextended_sp -#ifdef ASSERT -void frame::adjust_unextended_sp() { - // On aarch64, sites calling method handle intrinsics and lambda forms are treated - // as any other call site. Therefore, no special action is needed when we are - // returning to any of these call sites. - - if (_cb != nullptr) { - nmethod* sender_nm = _cb->as_nmethod_or_null(); - if (sender_nm != nullptr) { - // If the sender PC is a deoptimization point, get the original PC. - if (sender_nm->is_deopt_entry(_pc) || - sender_nm->is_deopt_mh_entry(_pc)) { - verify_deopt_original_pc(sender_nm, _unextended_sp); - } - } - } -} -#endif - - //------------------------------------------------------------------------------ // frame::sender_for_interpreter_frame frame frame::sender_for_interpreter_frame(RegisterMap* map) const { diff --git a/src/hotspot/cpu/aarch64/frame_aarch64.hpp b/src/hotspot/cpu/aarch64/frame_aarch64.hpp index da020b4234d..231710df7d7 100644 --- a/src/hotspot/cpu/aarch64/frame_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/frame_aarch64.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -141,8 +141,6 @@ int _offset_unextended_sp; // for use in stack-chunk frames }; - void adjust_unextended_sp() NOT_DEBUG_RETURN; - // true means _sp value is correct and we can use it to get the sender's sp // of the compiled frame, otherwise, _sp value may be invalid and we can use // _fp to get the sender's sp if PreserveFramePointer is enabled. @@ -152,11 +150,6 @@ return (intptr_t*) addr_at(offset); } -#ifdef ASSERT - // Used in frame::sender_for_{interpreter,compiled}_frame - static void verify_deopt_original_pc(nmethod* nm, intptr_t* unextended_sp); -#endif - public: // Constructors diff --git a/src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp b/src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp index 47ae93a4932..cb53d8663ad 100644 --- a/src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp +++ b/src/hotspot/cpu/aarch64/frame_aarch64.inline.hpp @@ -116,8 +116,6 @@ inline void frame::init(intptr_t* sp, intptr_t* fp, address pc) { } inline void frame::setup(address pc) { - adjust_unextended_sp(); - address original_pc = get_deopt_original_pc(); if (original_pc != nullptr) { _pc = original_pc; @@ -223,7 +221,6 @@ inline frame::frame(intptr_t* sp, intptr_t* fp) { // assert(_pc != nullptr, "no pc?"); _cb = CodeCache::find_blob(_pc); - adjust_unextended_sp(); address original_pc = get_deopt_original_pc(); if (original_pc != nullptr) { diff --git a/src/hotspot/cpu/arm/arm.ad b/src/hotspot/cpu/arm/arm.ad index 2835a256153..68fece5263d 100644 --- a/src/hotspot/cpu/arm/arm.ad +++ b/src/hotspot/cpu/arm/arm.ad @@ -1154,10 +1154,6 @@ RegMask Matcher::modL_proj_mask() { return RegMask(); } -const RegMask Matcher::method_handle_invoke_SP_save_mask() { - return FP_REGP_mask(); -} - bool maybe_far_call(const CallNode *n) { return !MacroAssembler::_reachable_from_cache(n->as_Call()->entry_point()); } @@ -1248,23 +1244,6 @@ encode %{ __ set_inst_mark(mark); %} - enc_class preserve_SP %{ - // preserve mark - address mark = __ inst_mark(); - DEBUG_ONLY(int off0 = __ offset()); - // FP is preserved across all calls, even compiled calls. - // Use it to preserve SP in places where the callee might change the SP. - __ mov(Rmh_SP_save, SP); - DEBUG_ONLY(int off1 = __ offset()); - assert(off1 - off0 == 4, "correct size prediction"); - // restore mark - __ set_inst_mark(mark); - %} - - enc_class restore_SP %{ - __ mov(SP, Rmh_SP_save); - %} - enc_class Java_Dynamic_Call (method meth) %{ Register R8_ic_reg = reg_to_register_object(Matcher::inline_cache_reg_encode()); assert(R8_ic_reg == Ricklass, "should be"); @@ -8799,7 +8778,6 @@ instruct safePoint_poll(iRegP poll, R12RegI tmp, flagsReg icc) %{ // Call Java Static Instruction instruct CallStaticJavaDirect( method meth ) %{ match(CallStaticJava); - predicate(! ((CallStaticJavaNode*)n)->is_method_handle_invoke()); effect(USE meth); ins_cost(CALL_COST); @@ -8808,20 +8786,6 @@ instruct CallStaticJavaDirect( method meth ) %{ ins_pipe(simple_call); %} -// Call Java Static Instruction (method handle version) -instruct CallStaticJavaHandle( method meth ) %{ - match(CallStaticJava); - predicate(((CallStaticJavaNode*)n)->is_method_handle_invoke()); - effect(USE meth); - // FP is saved by all callees (for interpreter stack correction). - // We use it here for a similar purpose, in {preserve,restore}_FP. - - ins_cost(CALL_COST); - format %{ "CALL,static/MethodHandle ==> " %} - ins_encode( SetInstMark, preserve_SP, Java_Static_Call( meth ), restore_SP, call_epilog, ClearInstMark ); - ins_pipe(simple_call); -%} - // Call Java Dynamic Instruction instruct CallDynamicJavaDirect( method meth ) %{ match(CallDynamicJava); diff --git a/src/hotspot/cpu/arm/arm_32.ad b/src/hotspot/cpu/arm/arm_32.ad index 1c15d55fbc3..00bf3bd61e4 100644 --- a/src/hotspot/cpu/arm/arm_32.ad +++ b/src/hotspot/cpu/arm/arm_32.ad @@ -1,5 +1,5 @@ // -// Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. +// Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. // DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. // // This code is free software; you can redistribute it and/or modify it @@ -432,8 +432,7 @@ OptoRegPair c2::return_value(int ideal_reg) { int MachCallStaticJavaNode::ret_addr_offset() { bool far = (_method == nullptr) ? maybe_far_call(this) : !cache_reachable(); - return ((far ? 3 : 1) + (_method_handle_invoke ? 1 : 0)) * - NativeInstruction::instruction_size; + return (far ? 3 : 1) * NativeInstruction::instruction_size; } int MachCallDynamicJavaNode::ret_addr_offset() { diff --git a/src/hotspot/cpu/arm/c1_FrameMap_arm.cpp b/src/hotspot/cpu/arm/c1_FrameMap_arm.cpp index 0fd113c8ceb..a820da4d283 100644 --- a/src/hotspot/cpu/arm/c1_FrameMap_arm.cpp +++ b/src/hotspot/cpu/arm/c1_FrameMap_arm.cpp @@ -174,11 +174,6 @@ LIR_Opr FrameMap::stack_pointer() { return FrameMap::SP_opr; } -LIR_Opr FrameMap::method_handle_invoke_SP_save_opr() { - assert(Rmh_SP_save == FP, "Fix register used for saving SP for MethodHandle calls"); - return FP_opr; -} - bool FrameMap::validate_frame() { int max_offset = in_bytes(framesize_in_bytes()); int java_index = 0; diff --git a/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp b/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp index 32da2c24d26..9983f2ce7a2 100644 --- a/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp +++ b/src/hotspot/cpu/arm/c1_Runtime1_arm.cpp @@ -275,14 +275,6 @@ OopMapSet* Runtime1::generate_exception_throw(StubAssembler* sasm, address targe } -static void restore_sp_for_method_handle(StubAssembler* sasm) { - // Restore SP from its saved reg (FP) if the exception PC is a MethodHandle call site. - __ ldr_s32(Rtemp, Address(Rthread, JavaThread::is_method_handle_return_offset())); - __ cmp(Rtemp, 0); - __ mov(SP, Rmh_SP_save, ne); -} - - OopMapSet* Runtime1::generate_handle_exception(StubId id, StubAssembler* sasm) { __ block_comment("generate_handle_exception"); @@ -339,7 +331,6 @@ OopMapSet* Runtime1::generate_handle_exception(StubId id, StubAssembler* sasm) { break; case StubId::c1_handle_exception_from_callee_id: restore_live_registers_without_return(sasm); // must not jump immediately to handler - restore_sp_for_method_handle(sasm); __ ret(); break; default: ShouldNotReachHere(); @@ -372,9 +363,6 @@ void Runtime1::generate_unwind_exception(StubAssembler* sasm) { // Jump to handler __ verify_not_null_oop(Rexception_obj); - // JSR292 extension - restore_sp_for_method_handle(sasm); - __ jump(R0); } diff --git a/src/hotspot/cpu/arm/frame_arm.cpp b/src/hotspot/cpu/arm/frame_arm.cpp index 2722f93edec..7a23296a3d4 100644 --- a/src/hotspot/cpu/arm/frame_arm.cpp +++ b/src/hotspot/cpu/arm/frame_arm.cpp @@ -329,56 +329,6 @@ JavaThread** frame::saved_thread_address(const frame& f) { return nullptr; } -//------------------------------------------------------------------------------ -// frame::verify_deopt_original_pc -// -// Verifies the calculated original PC of a deoptimization PC for the -// given unextended SP. The unextended SP might also be the saved SP -// for MethodHandle call sites. -#ifdef ASSERT -void frame::verify_deopt_original_pc(nmethod* nm, intptr_t* unextended_sp, bool is_method_handle_return) { - frame fr; - - // This is ugly but it's better than to change {get,set}_original_pc - // to take an SP value as argument. And it's only a debugging - // method anyway. - fr._unextended_sp = unextended_sp; - - address original_pc = nm->get_original_pc(&fr); - assert(nm->insts_contains_inclusive(original_pc), - "original PC must be in the main code section of the compiled method (or must be immediately following it)"); - assert(nm->is_method_handle_return(original_pc) == is_method_handle_return, "must be"); -} -#endif - -//------------------------------------------------------------------------------ -// frame::adjust_unextended_sp -void frame::adjust_unextended_sp() { - // same as on x86 - - // If we are returning to a compiled MethodHandle call site, the - // saved_fp will in fact be a saved value of the unextended SP. The - // simplest way to tell whether we are returning to such a call site - // is as follows: - - nmethod* sender_nm = (_cb == nullptr) ? nullptr : _cb->as_nmethod_or_null(); - if (sender_nm != nullptr) { - // If the sender PC is a deoptimization point, get the original - // PC. For MethodHandle call site the unextended_sp is stored in - // saved_fp. - if (sender_nm->is_deopt_mh_entry(_pc)) { - DEBUG_ONLY(verify_deopt_mh_original_pc(sender_nm, _fp)); - _unextended_sp = _fp; - } - else if (sender_nm->is_deopt_entry(_pc)) { - DEBUG_ONLY(verify_deopt_original_pc(sender_nm, _unextended_sp)); - } - else if (sender_nm->is_method_handle_return(_pc)) { - _unextended_sp = _fp; - } - } -} - //------------------------------------------------------------------------------ // frame::update_map_with_saved_link void frame::update_map_with_saved_link(RegisterMap* map, intptr_t** link_addr) { diff --git a/src/hotspot/cpu/arm/frame_arm.hpp b/src/hotspot/cpu/arm/frame_arm.hpp index dec27554a47..6d4ac042831 100644 --- a/src/hotspot/cpu/arm/frame_arm.hpp +++ b/src/hotspot/cpu/arm/frame_arm.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -85,20 +85,11 @@ // original sp. intptr_t* _unextended_sp; - void adjust_unextended_sp(); intptr_t* ptr_at_addr(int offset) const { return (intptr_t*) addr_at(offset); } -#ifdef ASSERT - // Used in frame::sender_for_{interpreter,compiled}_frame - static void verify_deopt_original_pc(nmethod* nm, intptr_t* unextended_sp, bool is_method_handle_return = false); - static void verify_deopt_mh_original_pc(nmethod* nm, intptr_t* unextended_sp) { - verify_deopt_original_pc(nm, unextended_sp, true); - } -#endif - public: // Constructors diff --git a/src/hotspot/cpu/arm/frame_arm.inline.hpp b/src/hotspot/cpu/arm/frame_arm.inline.hpp index 4be190f0504..42e034cfdc7 100644 --- a/src/hotspot/cpu/arm/frame_arm.inline.hpp +++ b/src/hotspot/cpu/arm/frame_arm.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -112,8 +112,6 @@ inline void frame::init(intptr_t* sp, intptr_t* unextended_sp, intptr_t* fp, add } inline void frame::setup(address pc) { - adjust_unextended_sp(); - address original_pc = get_deopt_original_pc(); if (original_pc != nullptr) { _pc = original_pc; diff --git a/src/hotspot/cpu/arm/register_arm.hpp b/src/hotspot/cpu/arm/register_arm.hpp index fca23d07fee..e0688af0d36 100644 --- a/src/hotspot/cpu/arm/register_arm.hpp +++ b/src/hotspot/cpu/arm/register_arm.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -364,7 +364,6 @@ class VFPSystemRegisterImpl : public AbstractRegisterImpl { // This does not seem to conflict with Rexception_pc // In case of issues, R3 might be OK but adapters calling the runtime would have to save it #define R5_mh R5 // MethodHandle register, used during the call setup -#define Rmh_SP_save FP // for C1 /* * C++ Interpreter Register Defines diff --git a/src/hotspot/cpu/arm/runtime_arm.cpp b/src/hotspot/cpu/arm/runtime_arm.cpp index ea4c9a76381..8d48de5795a 100644 --- a/src/hotspot/cpu/arm/runtime_arm.cpp +++ b/src/hotspot/cpu/arm/runtime_arm.cpp @@ -264,11 +264,6 @@ ExceptionBlob* OptoRuntime::generate_exception_blob() { __ raw_pop(FP, LR); - // Restore SP from its saved reg (FP) if the exception PC is a MethodHandle call site. - __ ldr(Rtemp, Address(Rthread, JavaThread::is_method_handle_return_offset())); - __ cmp(Rtemp, 0); - __ mov(SP, Rmh_SP_save, ne); - // R0 contains handler address // Since this may be the deopt blob we must set R5 to look like we returned // from the original pc that threw the exception diff --git a/src/hotspot/cpu/ppc/c1_FrameMap_ppc.cpp b/src/hotspot/cpu/ppc/c1_FrameMap_ppc.cpp index 8ce324a570b..cb9368f2ce9 100644 --- a/src/hotspot/cpu/ppc/c1_FrameMap_ppc.cpp +++ b/src/hotspot/cpu/ppc/c1_FrameMap_ppc.cpp @@ -374,15 +374,6 @@ LIR_Opr FrameMap::stack_pointer() { return SP_opr; } - -// JSR 292 -// On PPC64, there is no need to save the SP, because neither -// method handle intrinsics, nor compiled lambda forms modify it. -LIR_Opr FrameMap::method_handle_invoke_SP_save_opr() { - return LIR_OprFact::illegalOpr; -} - - bool FrameMap::validate_frame() { int max_offset = in_bytes(framesize_in_bytes()); int java_index = 0; diff --git a/src/hotspot/cpu/ppc/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad index 290369360fc..2c83b2d5765 100644 --- a/src/hotspot/cpu/ppc/ppc.ad +++ b/src/hotspot/cpu/ppc/ppc.ad @@ -2473,10 +2473,6 @@ RegMask Matcher::modL_proj_mask() { return RegMask(); } -const RegMask Matcher::method_handle_invoke_SP_save_mask() { - return RegMask(); -} - %} //----------ENCODING BLOCK----------------------------------------------------- @@ -3434,7 +3430,6 @@ encode %{ // Create the call node. CallDynamicJavaDirectSchedNode *call = new CallDynamicJavaDirectSchedNode(); - call->_method_handle_invoke = _method_handle_invoke; call->_vtable_index = _vtable_index; call->_method = _method; call->_optimized_virtual = _optimized_virtual; diff --git a/src/hotspot/cpu/riscv/c1_FrameMap_riscv.cpp b/src/hotspot/cpu/riscv/c1_FrameMap_riscv.cpp index d3ccd46048b..b3a0b261f54 100644 --- a/src/hotspot/cpu/riscv/c1_FrameMap_riscv.cpp +++ b/src/hotspot/cpu/riscv/c1_FrameMap_riscv.cpp @@ -377,11 +377,6 @@ LIR_Opr FrameMap::stack_pointer() { return FrameMap::sp_opr; } -// JSR 292 -LIR_Opr FrameMap::method_handle_invoke_SP_save_opr() { - return LIR_OprFact::illegalOpr; // Not needed on riscv -} - bool FrameMap::validate_frame() { return true; } diff --git a/src/hotspot/cpu/riscv/frame_riscv.cpp b/src/hotspot/cpu/riscv/frame_riscv.cpp index b677c980c78..19dbdd6aeae 100644 --- a/src/hotspot/cpu/riscv/frame_riscv.cpp +++ b/src/hotspot/cpu/riscv/frame_riscv.cpp @@ -217,8 +217,7 @@ bool frame::safe_for_sender(JavaThread *thread) { nmethod* nm = sender_blob->as_nmethod_or_null(); if (nm != nullptr) { - if (nm->is_deopt_mh_entry(sender_pc) || nm->is_deopt_entry(sender_pc) || - nm->method()->is_method_handle_intrinsic()) { + if (nm->is_deopt_entry(sender_pc) || nm->method()->is_method_handle_intrinsic()) { return false; } } @@ -427,49 +426,6 @@ JavaThread** frame::saved_thread_address(const frame& f) { return thread_addr; } -//------------------------------------------------------------------------------ -// frame::verify_deopt_original_pc -// -// Verifies the calculated original PC of a deoptimization PC for the -// given unextended SP. -#ifdef ASSERT -void frame::verify_deopt_original_pc(nmethod* nm, intptr_t* unextended_sp) { - frame fr; - - // This is ugly but it's better than to change {get,set}_original_pc - // to take an SP value as argument. And it's only a debugging - // method anyway. - fr._unextended_sp = unextended_sp; - - assert_cond(nm != nullptr); - address original_pc = nm->get_original_pc(&fr); - assert(nm->insts_contains_inclusive(original_pc), - "original PC must be in the main code section of the compiled method (or must be immediately following it)"); -} -#endif - -//------------------------------------------------------------------------------ -// frame::adjust_unextended_sp -#ifdef ASSERT -void frame::adjust_unextended_sp() { - // On riscv, sites calling method handle intrinsics and lambda forms are treated - // as any other call site. Therefore, no special action is needed when we are - // returning to any of these call sites. - - if (_cb != nullptr) { - nmethod* sender_nm = _cb->as_nmethod_or_null(); - if (sender_nm != nullptr) { - // If the sender PC is a deoptimization point, get the original PC. - if (sender_nm->is_deopt_entry(_pc) || - sender_nm->is_deopt_mh_entry(_pc)) { - verify_deopt_original_pc(sender_nm, _unextended_sp); - } - } - } -} -#endif - - //------------------------------------------------------------------------------ // frame::sender_for_interpreter_frame frame frame::sender_for_interpreter_frame(RegisterMap* map) const { diff --git a/src/hotspot/cpu/riscv/frame_riscv.hpp b/src/hotspot/cpu/riscv/frame_riscv.hpp index b4540c45ab8..ce5a8dde230 100644 --- a/src/hotspot/cpu/riscv/frame_riscv.hpp +++ b/src/hotspot/cpu/riscv/frame_riscv.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -179,17 +179,10 @@ int _offset_unextended_sp; // for use in stack-chunk frames }; - void adjust_unextended_sp() NOT_DEBUG_RETURN; - intptr_t* ptr_at_addr(int offset) const { return (intptr_t*) addr_at(offset); } -#ifdef ASSERT - // Used in frame::sender_for_{interpreter,compiled}_frame - static void verify_deopt_original_pc(nmethod* nm, intptr_t* unextended_sp); -#endif - public: // Constructors diff --git a/src/hotspot/cpu/riscv/frame_riscv.inline.hpp b/src/hotspot/cpu/riscv/frame_riscv.inline.hpp index fb31760e20b..51a203c548c 100644 --- a/src/hotspot/cpu/riscv/frame_riscv.inline.hpp +++ b/src/hotspot/cpu/riscv/frame_riscv.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, Red Hat Inc. All rights reserved. * Copyright (c) 2020, 2023, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -114,8 +114,6 @@ inline void frame::init(intptr_t* ptr_sp, intptr_t* ptr_fp, address pc) { } inline void frame::setup(address pc) { - adjust_unextended_sp(); - address original_pc = get_deopt_original_pc(); if (original_pc != nullptr) { _pc = original_pc; @@ -215,7 +213,6 @@ inline frame::frame(intptr_t* ptr_sp, intptr_t* ptr_fp) { // value. _cb = CodeCache::find_blob(_pc); - adjust_unextended_sp(); address original_pc = get_deopt_original_pc(); if (original_pc != nullptr) { diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad index d816f2405c4..1f14c499c34 100644 --- a/src/hotspot/cpu/riscv/riscv.ad +++ b/src/hotspot/cpu/riscv/riscv.ad @@ -2152,10 +2152,6 @@ RegMask Matcher::modL_proj_mask() { return RegMask(); } -const RegMask Matcher::method_handle_invoke_SP_save_mask() { - return FP_REG_mask(); -} - bool size_fits_all_mem_uses(AddPNode* addp, int shift) { assert_cond(addp != nullptr); for (DUIterator_Fast imax, i = addp->fast_outs(imax); i < imax; i++) { diff --git a/src/hotspot/cpu/s390/c1_FrameMap_s390.cpp b/src/hotspot/cpu/s390/c1_FrameMap_s390.cpp index ddba445154a..e219e9bbb40 100644 --- a/src/hotspot/cpu/s390/c1_FrameMap_s390.cpp +++ b/src/hotspot/cpu/s390/c1_FrameMap_s390.cpp @@ -282,13 +282,6 @@ LIR_Opr FrameMap::stack_pointer() { return Z_SP_opr; } -// JSR 292 -// On ZARCH_64, there is no need to save the SP, because neither -// method handle intrinsics nor compiled lambda forms modify it. -LIR_Opr FrameMap::method_handle_invoke_SP_save_opr() { - return LIR_OprFact::illegalOpr; -} - bool FrameMap::validate_frame() { return true; } diff --git a/src/hotspot/cpu/s390/s390.ad b/src/hotspot/cpu/s390/s390.ad index e9377733d2d..cfc8b19534b 100644 --- a/src/hotspot/cpu/s390/s390.ad +++ b/src/hotspot/cpu/s390/s390.ad @@ -1980,11 +1980,6 @@ RegMask Matcher::modL_proj_mask() { return _Z_RARG3_LONG_REG_mask; } -// Copied from sparc. -const RegMask Matcher::method_handle_invoke_SP_save_mask() { - return RegMask(); -} - // Should the matcher clone input 'm' of node 'n'? bool Matcher::pd_clone_node(Node* n, Node* m, Matcher::MStack& mstack) { if (is_encode_and_store_pattern(n, m)) { diff --git a/src/hotspot/cpu/x86/c1_FrameMap_x86.cpp b/src/hotspot/cpu/x86/c1_FrameMap_x86.cpp index bdbab432180..68c9814fd20 100644 --- a/src/hotspot/cpu/x86/c1_FrameMap_x86.cpp +++ b/src/hotspot/cpu/x86/c1_FrameMap_x86.cpp @@ -326,13 +326,6 @@ LIR_Opr FrameMap::stack_pointer() { return FrameMap::rsp_opr; } -// JSR 292 -// On x86, there is no need to save the SP, because neither -// method handle intrinsics, nor compiled lambda forms modify it. -LIR_Opr FrameMap::method_handle_invoke_SP_save_opr() { - return LIR_OprFact::illegalOpr; -} - bool FrameMap::validate_frame() { return true; } diff --git a/src/hotspot/cpu/x86/frame_x86.cpp b/src/hotspot/cpu/x86/frame_x86.cpp index 46ffda93699..5f52f2fabf2 100644 --- a/src/hotspot/cpu/x86/frame_x86.cpp +++ b/src/hotspot/cpu/x86/frame_x86.cpp @@ -219,8 +219,7 @@ bool frame::safe_for_sender(JavaThread *thread) { nmethod* nm = sender_blob->as_nmethod_or_null(); if (nm != nullptr) { - if (nm->is_deopt_mh_entry(sender_pc) || nm->is_deopt_entry(sender_pc) || - nm->method()->is_method_handle_intrinsic()) { + if (nm->is_deopt_entry(sender_pc) || nm->method()->is_method_handle_intrinsic()) { return false; } } @@ -443,47 +442,6 @@ JavaThread** frame::saved_thread_address(const frame& f) { return thread_addr; } -//------------------------------------------------------------------------------ -// frame::verify_deopt_original_pc -// -// Verifies the calculated original PC of a deoptimization PC for the -// given unextended SP. -#ifdef ASSERT -void frame::verify_deopt_original_pc(nmethod* nm, intptr_t* unextended_sp) { - frame fr; - - // This is ugly but it's better than to change {get,set}_original_pc - // to take an SP value as argument. And it's only a debugging - // method anyway. - fr._unextended_sp = unextended_sp; - - address original_pc = nm->get_original_pc(&fr); - assert(nm->insts_contains_inclusive(original_pc), - "original PC must be in the main code section of the compiled method (or must be immediately following it) original_pc: " INTPTR_FORMAT " unextended_sp: " INTPTR_FORMAT " name: %s", p2i(original_pc), p2i(unextended_sp), nm->name()); -} -#endif - -//------------------------------------------------------------------------------ -// frame::adjust_unextended_sp -#ifdef ASSERT -void frame::adjust_unextended_sp() { - // On x86, sites calling method handle intrinsics and lambda forms are treated - // as any other call site. Therefore, no special action is needed when we are - // returning to any of these call sites. - - if (_cb != nullptr) { - nmethod* sender_nm = _cb->as_nmethod_or_null(); - if (sender_nm != nullptr) { - // If the sender PC is a deoptimization point, get the original PC. - if (sender_nm->is_deopt_entry(_pc) || - sender_nm->is_deopt_mh_entry(_pc)) { - verify_deopt_original_pc(sender_nm, _unextended_sp); - } - } - } -} -#endif - //------------------------------------------------------------------------------ // frame::sender_for_interpreter_frame frame frame::sender_for_interpreter_frame(RegisterMap* map) const { diff --git a/src/hotspot/cpu/x86/frame_x86.hpp b/src/hotspot/cpu/x86/frame_x86.hpp index f3034ee9263..19f37c42cf4 100644 --- a/src/hotspot/cpu/x86/frame_x86.hpp +++ b/src/hotspot/cpu/x86/frame_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -138,17 +138,10 @@ int _offset_unextended_sp; // for use in stack-chunk frames }; - void adjust_unextended_sp() NOT_DEBUG_RETURN; - intptr_t* ptr_at_addr(int offset) const { return (intptr_t*) addr_at(offset); } -#ifdef ASSERT - // Used in frame::sender_for_{interpreter,compiled}_frame - static void verify_deopt_original_pc(nmethod* nm, intptr_t* unextended_sp); -#endif - public: // Constructors diff --git a/src/hotspot/cpu/x86/frame_x86.inline.hpp b/src/hotspot/cpu/x86/frame_x86.inline.hpp index afc4ab8767b..ca51fe66786 100644 --- a/src/hotspot/cpu/x86/frame_x86.inline.hpp +++ b/src/hotspot/cpu/x86/frame_x86.inline.hpp @@ -111,8 +111,6 @@ inline void frame::init(intptr_t* sp, intptr_t* fp, address pc) { } inline void frame::setup(address pc) { - adjust_unextended_sp(); - address original_pc = get_deopt_original_pc(); if (original_pc != nullptr) { _pc = original_pc; @@ -209,7 +207,6 @@ inline frame::frame(intptr_t* sp, intptr_t* fp) { // assert(_pc != nullptr, "no pc?"); _cb = CodeCache::find_blob(_pc); - adjust_unextended_sp(); address original_pc = get_deopt_original_pc(); if (original_pc != nullptr) { diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad index 0b254966db6..b40f9e2924a 100644 --- a/src/hotspot/cpu/x86/x86_64.ad +++ b/src/hotspot/cpu/x86/x86_64.ad @@ -1697,11 +1697,6 @@ RegMask Matcher::modL_proj_mask() { return LONG_RDX_REG_mask(); } -// Register for saving SP into on method handle invokes. Not used on x86_64. -const RegMask Matcher::method_handle_invoke_SP_save_mask() { - return NO_REG_mask(); -} - %} //----------ENCODING BLOCK----------------------------------------------------- diff --git a/src/hotspot/os/posix/signals_posix.cpp b/src/hotspot/os/posix/signals_posix.cpp index 886bd453415..714eac12d22 100644 --- a/src/hotspot/os/posix/signals_posix.cpp +++ b/src/hotspot/os/posix/signals_posix.cpp @@ -621,9 +621,7 @@ int JVM_HANDLE_XXX_SIGNAL(int sig, siginfo_t* info, if (cb != nullptr && cb->is_nmethod()) { nmethod* nm = cb->as_nmethod(); assert(nm->insts_contains_inclusive(pc), ""); - address deopt = nm->is_method_handle_return(pc) ? - nm->deopt_mh_handler_begin() : - nm->deopt_handler_begin(); + address deopt = nm->deopt_handler_begin(); assert(deopt != nullptr, ""); frame fr = os::fetch_frame_from_context(uc); diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 875e97ce038..c9ef08e3510 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -2797,9 +2797,7 @@ LONG WINAPI topLevelExceptionFilter(struct _EXCEPTION_POINTERS* exceptionInfo) { if (cb != nullptr && cb->is_nmethod()) { nmethod* nm = cb->as_nmethod(); frame fr = os::fetch_frame_from_context((void*)exceptionInfo->ContextRecord); - address deopt = nm->is_method_handle_return(pc) ? - nm->deopt_mh_handler_begin() : - nm->deopt_handler_begin(); + address deopt = nm->deopt_handler_begin(); assert(nm->insts_contains_inclusive(pc), ""); nm->set_original_pc(&fr, pc); // Set pc to handler diff --git a/src/hotspot/share/asm/codeBuffer.hpp b/src/hotspot/share/asm/codeBuffer.hpp index 35bbd2f657f..430d4949467 100644 --- a/src/hotspot/share/asm/codeBuffer.hpp +++ b/src/hotspot/share/asm/codeBuffer.hpp @@ -57,7 +57,6 @@ public: OSR_Entry, Exceptions, // Offset where exception handler lives Deopt, // Offset where deopt handler lives - DeoptMH, // Offset where MethodHandle deopt handler lives UnwindHandler, // Offset to default unwind handler max_Entries }; @@ -77,7 +76,6 @@ public: _values[OSR_Entry ] = 0; _values[Exceptions ] = -1; _values[Deopt ] = -1; - _values[DeoptMH ] = -1; _values[UnwindHandler ] = -1; } diff --git a/src/hotspot/share/c1/c1_Compilation.cpp b/src/hotspot/share/c1/c1_Compilation.cpp index bb5ceb0106b..368cf604eeb 100644 --- a/src/hotspot/share/c1/c1_Compilation.cpp +++ b/src/hotspot/share/c1/c1_Compilation.cpp @@ -310,14 +310,6 @@ void Compilation::emit_code_epilog(LIR_Assembler* assembler) { code_offsets->set_value(CodeOffsets::Deopt, assembler->emit_deopt_handler()); CHECK_BAILOUT(); - // Emit the MethodHandle deopt handler code (if required). - if (has_method_handle_invokes()) { - // We can use the same code as for the normal deopt handler, we - // just need a different entry point address. - code_offsets->set_value(CodeOffsets::DeoptMH, assembler->emit_deopt_handler()); - CHECK_BAILOUT(); - } - // Emit the handler to remove the activation from the stack and // dispatch to the caller. offsets()->set_value(CodeOffsets::UnwindHandler, assembler->emit_unwind_handler()); @@ -574,7 +566,6 @@ Compilation::Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* metho , _has_unsafe_access(false) , _has_irreducible_loops(false) , _would_profile(false) -, _has_method_handle_invokes(false) , _has_reserved_stack_access(method->has_reserved_stack_access()) , _has_monitors(method->is_synchronized() || method->has_monitor_bytecodes()) , _has_scoped_access(method->is_scoped()) diff --git a/src/hotspot/share/c1/c1_Compilation.hpp b/src/hotspot/share/c1/c1_Compilation.hpp index 0c6b95e66c5..5125e0bbe0a 100644 --- a/src/hotspot/share/c1/c1_Compilation.hpp +++ b/src/hotspot/share/c1/c1_Compilation.hpp @@ -79,7 +79,6 @@ class Compilation: public StackObj { bool _has_unsafe_access; bool _has_irreducible_loops; bool _would_profile; - bool _has_method_handle_invokes; // True if this method has MethodHandle invokes. bool _has_reserved_stack_access; bool _has_monitors; // Fastpath monitors detection for Continuations bool _has_scoped_access; // For shared scope closure @@ -180,10 +179,6 @@ class Compilation: public StackObj { // Statistics gathering void notice_inlined_method(ciMethod* method); - // JSR 292 - bool has_method_handle_invokes() const { return _has_method_handle_invokes; } - void set_has_method_handle_invokes(bool z) { _has_method_handle_invokes = z; } - bool has_reserved_stack_access() const { return _has_reserved_stack_access; } void set_has_reserved_stack_access(bool z) { _has_reserved_stack_access = z; } diff --git a/src/hotspot/share/c1/c1_FrameMap.hpp b/src/hotspot/share/c1/c1_FrameMap.hpp index f10c4d3f226..67ae92e9875 100644 --- a/src/hotspot/share/c1/c1_FrameMap.hpp +++ b/src/hotspot/share/c1/c1_FrameMap.hpp @@ -155,9 +155,6 @@ class FrameMap : public CompilationResourceObj { // Opr representing the stack_pointer on this platform static LIR_Opr stack_pointer(); - // JSR 292 - static LIR_Opr method_handle_invoke_SP_save_opr(); - static BasicTypeArray* signature_type_array_for(const ciMethod* method); // for outgoing calls, these also update the reserved area to diff --git a/src/hotspot/share/c1/c1_IR.cpp b/src/hotspot/share/c1/c1_IR.cpp index ae8332116b3..238a9bdda0d 100644 --- a/src/hotspot/share/c1/c1_IR.cpp +++ b/src/hotspot/share/c1/c1_IR.cpp @@ -190,7 +190,6 @@ CodeEmitInfo::CodeEmitInfo(ValueStack* stack, XHandlers* exception_handlers, boo , _exception_handlers(exception_handlers) , _oop_map(nullptr) , _stack(stack) - , _is_method_handle_invoke(false) , _deoptimize_on_exception(deoptimize_on_exception) , _force_reexecute(false) { assert(_stack != nullptr, "must be non null"); @@ -203,7 +202,6 @@ CodeEmitInfo::CodeEmitInfo(CodeEmitInfo* info, ValueStack* stack) , _exception_handlers(nullptr) , _oop_map(nullptr) , _stack(stack == nullptr ? info->_stack : stack) - , _is_method_handle_invoke(info->_is_method_handle_invoke) , _deoptimize_on_exception(info->_deoptimize_on_exception) , _force_reexecute(info->_force_reexecute) { @@ -218,7 +216,7 @@ void CodeEmitInfo::record_debug_info(DebugInformationRecorder* recorder, int pc_ // record the safepoint before recording the debug info for enclosing scopes recorder->add_safepoint(pc_offset, _oop_map->deep_copy()); bool reexecute = _force_reexecute || _scope_debug_info->should_reexecute(); - _scope_debug_info->record_debug_info(recorder, pc_offset, reexecute, _is_method_handle_invoke); + _scope_debug_info->record_debug_info(recorder, pc_offset, reexecute); recorder->end_safepoint(pc_offset); } diff --git a/src/hotspot/share/c1/c1_IR.hpp b/src/hotspot/share/c1/c1_IR.hpp index a9a7a026390..d6a4cddb9d7 100644 --- a/src/hotspot/share/c1/c1_IR.hpp +++ b/src/hotspot/share/c1/c1_IR.hpp @@ -234,7 +234,7 @@ class IRScopeDebugInfo: public CompilationResourceObj { //Whether we should reexecute this bytecode for deopt bool should_reexecute(); - void record_debug_info(DebugInformationRecorder* recorder, int pc_offset, bool reexecute, bool is_method_handle_invoke = false) { + void record_debug_info(DebugInformationRecorder* recorder, int pc_offset, bool reexecute) { if (caller() != nullptr) { // Order is significant: Must record caller first. caller()->record_debug_info(recorder, pc_offset, false/*reexecute*/); @@ -248,7 +248,7 @@ class IRScopeDebugInfo: public CompilationResourceObj { bool has_ea_local_in_scope = false; bool arg_escape = false; recorder->describe_scope(pc_offset, methodHandle(), scope()->method(), bci(), - reexecute, rethrow_exception, is_method_handle_invoke, return_oop, + reexecute, rethrow_exception, return_oop, has_ea_local_in_scope, arg_escape, locvals, expvals, monvals); } }; @@ -262,7 +262,6 @@ class CodeEmitInfo: public CompilationResourceObj { XHandlers* _exception_handlers; OopMap* _oop_map; ValueStack* _stack; // used by deoptimization (contains also monitors - bool _is_method_handle_invoke; // true if the associated call site is a MethodHandle call site. bool _deoptimize_on_exception; bool _force_reexecute; // force the reexecute flag on, used for patching stub @@ -288,9 +287,6 @@ class CodeEmitInfo: public CompilationResourceObj { void add_register_oop(LIR_Opr opr); void record_debug_info(DebugInformationRecorder* recorder, int pc_offset); - bool is_method_handle_invoke() const { return _is_method_handle_invoke; } - void set_is_method_handle_invoke(bool x) { _is_method_handle_invoke = x; } - bool force_reexecute() const { return _force_reexecute; } void set_force_reexecute() { _force_reexecute = true; } diff --git a/src/hotspot/share/c1/c1_LIR.cpp b/src/hotspot/share/c1/c1_LIR.cpp index f11e178bd55..012c0f92f25 100644 --- a/src/hotspot/share/c1/c1_LIR.cpp +++ b/src/hotspot/share/c1/c1_LIR.cpp @@ -709,11 +709,6 @@ void LIR_OpVisitState::visit(LIR_Op* op) { } if (opJavaCall->_info) do_info(opJavaCall->_info); - if (FrameMap::method_handle_invoke_SP_save_opr() != LIR_OprFact::illegalOpr && - opJavaCall->is_method_handle_invoke()) { - opJavaCall->_method_handle_invoke_SP_save_opr = FrameMap::method_handle_invoke_SP_save_opr(); - do_temp(opJavaCall->_method_handle_invoke_SP_save_opr); - } do_call(); if (opJavaCall->_result->is_valid()) do_output(opJavaCall->_result); diff --git a/src/hotspot/share/c1/c1_LIR.hpp b/src/hotspot/share/c1/c1_LIR.hpp index 0427c868e6f..847184731ce 100644 --- a/src/hotspot/share/c1/c1_LIR.hpp +++ b/src/hotspot/share/c1/c1_LIR.hpp @@ -1176,7 +1176,6 @@ class LIR_OpJavaCall: public LIR_OpCall { private: ciMethod* _method; LIR_Opr _receiver; - LIR_Opr _method_handle_invoke_SP_save_opr; // Used in LIR_OpVisitState::visit to store the reference to FrameMap::method_handle_invoke_SP_save_opr. public: LIR_OpJavaCall(LIR_Code code, ciMethod* method, @@ -1186,7 +1185,6 @@ class LIR_OpJavaCall: public LIR_OpCall { : LIR_OpCall(code, addr, result, arguments, info) , _method(method) , _receiver(receiver) - , _method_handle_invoke_SP_save_opr(LIR_OprFact::illegalOpr) { assert(is_in_range(code, begin_opJavaCall, end_opJavaCall), "code check"); } LIR_OpJavaCall(LIR_Code code, ciMethod* method, @@ -1195,7 +1193,6 @@ class LIR_OpJavaCall: public LIR_OpCall { : LIR_OpCall(code, (address)vtable_offset, result, arguments, info) , _method(method) , _receiver(receiver) - , _method_handle_invoke_SP_save_opr(LIR_OprFact::illegalOpr) { assert(is_in_range(code, begin_opJavaCall, end_opJavaCall), "code check"); } LIR_Opr receiver() const { return _receiver; } diff --git a/src/hotspot/share/c1/c1_LIRAssembler.cpp b/src/hotspot/share/c1/c1_LIRAssembler.cpp index 6dbd35f054f..e6963c00c6a 100644 --- a/src/hotspot/share/c1/c1_LIRAssembler.cpp +++ b/src/hotspot/share/c1/c1_LIRAssembler.cpp @@ -478,12 +478,6 @@ void LIR_Assembler::emit_call(LIR_OpJavaCall* op) { fatal("unexpected op code: %s", op->name()); break; } - - // JSR 292 - // Record if this method has MethodHandle invokes. - if (op->is_method_handle_invoke()) { - compilation()->set_has_method_handle_invokes(true); - } } diff --git a/src/hotspot/share/c1/c1_LIRGenerator.cpp b/src/hotspot/share/c1/c1_LIRGenerator.cpp index 66adfa5ed66..f6807abcd7a 100644 --- a/src/hotspot/share/c1/c1_LIRGenerator.cpp +++ b/src/hotspot/share/c1/c1_LIRGenerator.cpp @@ -2712,19 +2712,7 @@ void LIRGenerator::do_Invoke(Invoke* x) { // emit invoke code assert(receiver->is_illegal() || receiver->is_equal(LIR_Assembler::receiverOpr()), "must match"); - // JSR 292 - // Preserve the SP over MethodHandle call sites, if needed. ciMethod* target = x->target(); - bool is_method_handle_invoke = (// %%% FIXME: Are both of these relevant? - target->is_method_handle_intrinsic() || - target->is_compiled_lambda_form()); - if (is_method_handle_invoke) { - info->set_is_method_handle_invoke(true); - if(FrameMap::method_handle_invoke_SP_save_opr() != LIR_OprFact::illegalOpr) { - __ move(FrameMap::stack_pointer(), FrameMap::method_handle_invoke_SP_save_opr()); - } - } - switch (x->code()) { case Bytecodes::_invokestatic: __ call_static(target, result_register, @@ -2757,13 +2745,6 @@ void LIRGenerator::do_Invoke(Invoke* x) { break; } - // JSR 292 - // Restore the SP after MethodHandle call sites, if needed. - if (is_method_handle_invoke - && FrameMap::method_handle_invoke_SP_save_opr() != LIR_OprFact::illegalOpr) { - __ move(FrameMap::method_handle_invoke_SP_save_opr(), FrameMap::stack_pointer()); - } - if (result_register->is_valid()) { LIR_Opr result = rlock_result(x); __ move(result_register, result); diff --git a/src/hotspot/share/c1/c1_Runtime1.cpp b/src/hotspot/share/c1/c1_Runtime1.cpp index 637c7c46ef4..a4c956ff5be 100644 --- a/src/hotspot/share/c1/c1_Runtime1.cpp +++ b/src/hotspot/share/c1/c1_Runtime1.cpp @@ -541,9 +541,6 @@ extern void vm_exit(int code); // unpack_with_exception entry instead. This makes life for the exception blob easier // because making that same check and diverting is painful from assembly language. JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* current, oopDesc* ex, address pc, nmethod*& nm)) - // Reset method handle flag. - current->set_is_method_handle_return(false); - Handle exception(current, ex); // This function is called when we are about to throw an exception. Therefore, @@ -622,8 +619,6 @@ JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* c if (guard_pages_enabled) { address fast_continuation = nm->handler_for_exception_and_pc(exception, pc); if (fast_continuation != nullptr) { - // Set flag if return address is a method handle call site. - current->set_is_method_handle_return(nm->is_method_handle_return(pc)); return fast_continuation; } } @@ -660,8 +655,6 @@ JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* c } current->set_vm_result_oop(exception()); - // Set flag if return address is a method handle call site. - current->set_is_method_handle_return(nm->is_method_handle_return(pc)); if (log_is_enabled(Info, exceptions)) { ResourceMark rm; diff --git a/src/hotspot/share/code/debugInfoRec.cpp b/src/hotspot/share/code/debugInfoRec.cpp index 8449f5d6929..41d944ec76f 100644 --- a/src/hotspot/share/code/debugInfoRec.cpp +++ b/src/hotspot/share/code/debugInfoRec.cpp @@ -283,7 +283,6 @@ void DebugInformationRecorder::describe_scope(int pc_offset, int bci, bool reexecute, bool rethrow_exception, - bool is_method_handle_invoke, bool return_oop, bool has_ea_local_in_scope, bool arg_escape, @@ -301,7 +300,6 @@ void DebugInformationRecorder::describe_scope(int pc_offset, // Record flags into pcDesc. last_pd->set_should_reexecute(reexecute); last_pd->set_rethrow_exception(rethrow_exception); - last_pd->set_is_method_handle_invoke(is_method_handle_invoke); last_pd->set_return_oop(return_oop); last_pd->set_has_ea_local_in_scope(has_ea_local_in_scope); last_pd->set_arg_escape(arg_escape); diff --git a/src/hotspot/share/code/debugInfoRec.hpp b/src/hotspot/share/code/debugInfoRec.hpp index f6d7cf6d278..d18208e17c4 100644 --- a/src/hotspot/share/code/debugInfoRec.hpp +++ b/src/hotspot/share/code/debugInfoRec.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -105,7 +105,6 @@ class DebugInformationRecorder: public ResourceObj { int bci, bool reexecute, bool rethrow_exception = false, - bool is_method_handle_invoke = false, bool return_oop = false, bool has_ea_local_in_scope = false, bool arg_escape = false, diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp index c0091cd2f65..1540fa0333a 100644 --- a/src/hotspot/share/code/nmethod.cpp +++ b/src/hotspot/share/code/nmethod.cpp @@ -465,14 +465,6 @@ static int adjust_pcs_size(int pcs_size) { return nsize; } -bool nmethod::is_method_handle_return(address return_pc) { - if (!has_method_handle_invokes()) return false; - PcDesc* pd = pc_desc_at(return_pc); - if (pd == nullptr) - return false; - return pd->is_method_handle_invoke(); -} - // Returns a string version of the method state. const char* nmethod::state() const { int state = get_state(); @@ -1231,7 +1223,6 @@ void nmethod::init_defaults(CodeBuffer *code_buffer, CodeOffsets* offsets) { _state = not_installed; _has_unsafe_access = 0; - _has_method_handle_invokes = 0; _has_wide_vectors = 0; _has_monitors = 0; _has_scoped_access = 0; @@ -1310,7 +1301,6 @@ nmethod::nmethod( // Native wrappers do not have deopt handlers. Make the values // something that will never match a pc like the nmethod vtable entry _deopt_handler_offset = 0; - _deopt_mh_handler_offset = 0; _unwind_handler_offset = 0; CHECKED_CAST(_oops_size, uint16_t, align_up(code_buffer->total_oop_size(), oopSize)); @@ -1458,11 +1448,6 @@ nmethod::nmethod( } else { _deopt_handler_offset = -1; } - if (offsets->value(CodeOffsets::DeoptMH) != -1) { - _deopt_mh_handler_offset = code_offset() + offsets->value(CodeOffsets::DeoptMH); - } else { - _deopt_mh_handler_offset = -1; - } } else #endif { @@ -1472,11 +1457,6 @@ nmethod::nmethod( _exception_offset = _stub_offset + offsets->value(CodeOffsets::Exceptions); _deopt_handler_offset = _stub_offset + offsets->value(CodeOffsets::Deopt); - if (offsets->value(CodeOffsets::DeoptMH) != -1) { - _deopt_mh_handler_offset = _stub_offset + offsets->value(CodeOffsets::DeoptMH); - } else { - _deopt_mh_handler_offset = -1; - } } if (offsets->value(CodeOffsets::UnwindHandler) != -1) { // C1 generates UnwindHandler at the end of instructions section. @@ -2693,15 +2673,6 @@ void nmethod::copy_scopes_pcs(PcDesc* pcs, int count) { "must end with a sentinel"); #endif //ASSERT - // Search for MethodHandle invokes and tag the nmethod. - for (int i = 0; i < count; i++) { - if (pcs[i].is_method_handle_invoke()) { - set_has_method_handle_invokes(true); - break; - } - } - assert(has_method_handle_invokes() == (_deopt_mh_handler_offset != -1), "must have deopt mh handler"); - int size = count * sizeof(PcDesc); assert(scopes_pcs_size() >= size, "oob"); memcpy(scopes_pcs_begin(), pcs, size); @@ -3711,7 +3682,6 @@ const char* nmethod::nmethod_section_label(address pos) const { if (pos == code_begin()) label = "[Instructions begin]"; if (pos == entry_point()) label = "[Entry Point]"; if (pos == verified_entry_point()) label = "[Verified Entry Point]"; - if (has_method_handle_invokes() && (pos == deopt_mh_handler_begin())) label = "[Deopt MH Handler Code]"; if (pos == consts_begin() && pos != insts_begin()) label = "[Constants]"; // Check stub_code before checking exception_handler or deopt_handler. if (pos == this->stub_begin()) label = "[Stub Code]"; diff --git a/src/hotspot/share/code/nmethod.hpp b/src/hotspot/share/code/nmethod.hpp index 8dfccb07891..1e876657098 100644 --- a/src/hotspot/share/code/nmethod.hpp +++ b/src/hotspot/share/code/nmethod.hpp @@ -226,9 +226,6 @@ class nmethod : public CodeBlob { // All deoptee's will resume execution at this location described by // this offset. int _deopt_handler_offset; - // All deoptee's at a MethodHandle call site will resume execution - // at this location described by this offset. - int _deopt_mh_handler_offset; // Offset (from insts_end) of the unwind handler if it exists int16_t _unwind_handler_offset; // Number of arguments passed on the stack @@ -267,7 +264,6 @@ class nmethod : public CodeBlob { // set during construction uint8_t _has_unsafe_access:1, // May fault due to unsafe access. - _has_method_handle_invokes:1,// Has this method MethodHandle invokes? _has_wide_vectors:1, // Preserve wide vectors at safepoints _has_monitors:1, // Fastpath monitor detection for continuations _has_scoped_access:1, // used by for shared scope closure (scopedMemoryAccess.cpp) @@ -606,7 +602,6 @@ public: address stub_end () const { return code_end() ; } address exception_begin () const { return header_begin() + _exception_offset ; } address deopt_handler_begin () const { return header_begin() + _deopt_handler_offset ; } - address deopt_mh_handler_begin() const { return header_begin() + _deopt_mh_handler_offset ; } address unwind_handler_begin () const { return _unwind_handler_offset != -1 ? (insts_end() - _unwind_handler_offset) : nullptr; } oop* oops_begin () const { return (oop*) data_begin(); } oop* oops_end () const { return (oop*) data_end(); } @@ -745,9 +740,6 @@ public: bool has_scoped_access() const { return _has_scoped_access; } void set_has_scoped_access(bool z) { _has_scoped_access = z; } - bool has_method_handle_invokes() const { return _has_method_handle_invokes; } - void set_has_method_handle_invokes(bool z) { _has_method_handle_invokes = z; } - bool has_wide_vectors() const { return _has_wide_vectors; } void set_has_wide_vectors(bool z) { _has_wide_vectors = z; } @@ -818,12 +810,9 @@ public: ExceptionCache* exception_cache_entry_for_exception(Handle exception); - // MethodHandle - bool is_method_handle_return(address return_pc); // Deopt // Return true is the PC is one would expect if the frame is being deopted. inline bool is_deopt_pc(address pc); - inline bool is_deopt_mh_entry(address pc); inline bool is_deopt_entry(address pc); // Accessor/mutator for the original pc of a frame before a frame was deopted. diff --git a/src/hotspot/share/code/nmethod.inline.hpp b/src/hotspot/share/code/nmethod.inline.hpp index 62c8eb723ea..44331db669c 100644 --- a/src/hotspot/share/code/nmethod.inline.hpp +++ b/src/hotspot/share/code/nmethod.inline.hpp @@ -31,16 +31,12 @@ #include "runtime/atomicAccess.hpp" #include "runtime/frame.hpp" -inline bool nmethod::is_deopt_pc(address pc) { return is_deopt_entry(pc) || is_deopt_mh_entry(pc); } +inline bool nmethod::is_deopt_pc(address pc) { return is_deopt_entry(pc); } inline bool nmethod::is_deopt_entry(address pc) { return pc == deopt_handler_begin(); } -inline bool nmethod::is_deopt_mh_entry(address pc) { - return pc == deopt_mh_handler_begin(); -} - // class ExceptionCache methods inline int ExceptionCache::count() { return AtomicAccess::load_acquire(&_count); } diff --git a/src/hotspot/share/code/pcDesc.hpp b/src/hotspot/share/code/pcDesc.hpp index 8048c3909c7..d8abe19ad35 100644 --- a/src/hotspot/share/code/pcDesc.hpp +++ b/src/hotspot/share/code/pcDesc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,11 +40,10 @@ class PcDesc { enum { PCDESC_reexecute = 1 << 0, - PCDESC_is_method_handle_invoke = 1 << 1, - PCDESC_return_oop = 1 << 2, - PCDESC_rethrow_exception = 1 << 3, - PCDESC_has_ea_local_in_scope = 1 << 4, - PCDESC_arg_escape = 1 << 5 + PCDESC_return_oop = 1 << 1, + PCDESC_rethrow_exception = 1 << 2, + PCDESC_has_ea_local_in_scope = 1 << 3, + PCDESC_arg_escape = 1 << 4 }; int _flags; @@ -85,9 +84,6 @@ class PcDesc { _flags == pd->_flags; } - bool is_method_handle_invoke() const { return (_flags & PCDESC_is_method_handle_invoke) != 0; } - void set_is_method_handle_invoke(bool z) { set_flag(PCDESC_is_method_handle_invoke, z); } - bool return_oop() const { return (_flags & PCDESC_return_oop) != 0; } void set_return_oop(bool z) { set_flag(PCDESC_return_oop, z); } diff --git a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp index 3a9fbc54bf9..ce617a4a514 100644 --- a/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp +++ b/src/hotspot/share/jvmci/jvmciCodeInstaller.cpp @@ -1141,7 +1141,7 @@ int CodeInstaller::map_jvmci_bci(int bci) { return bci; } -void CodeInstaller::record_scope(jint pc_offset, HotSpotCompiledCodeStream* stream, u1 debug_info_flags, bool full_info, bool is_mh_invoke, bool return_oop, JVMCI_TRAPS) { +void CodeInstaller::record_scope(jint pc_offset, HotSpotCompiledCodeStream* stream, u1 debug_info_flags, bool full_info, bool return_oop, JVMCI_TRAPS) { if (full_info) { read_virtual_objects(stream, JVMCI_CHECK); } @@ -1184,7 +1184,7 @@ void CodeInstaller::record_scope(jint pc_offset, HotSpotCompiledCodeStream* stre // has_ea_local_in_scope and arg_escape should be added to JVMCI const bool has_ea_local_in_scope = false; const bool arg_escape = false; - _debug_recorder->describe_scope(pc_offset, method, nullptr, bci, reexecute, rethrow_exception, is_mh_invoke, return_oop, + _debug_recorder->describe_scope(pc_offset, method, nullptr, bci, reexecute, rethrow_exception, return_oop, has_ea_local_in_scope, arg_escape, locals_token, stack_token, monitors_token); } @@ -1242,14 +1242,8 @@ void CodeInstaller::site_Call(CodeBuffer& buffer, u1 tag, jint pc_offset, HotSpo _debug_recorder->add_safepoint(next_pc_offset, map); if (!method.is_null()) { - vmIntrinsics::ID iid = method->intrinsic_id(); - bool is_mh_invoke = false; - if (direct_call) { - is_mh_invoke = !method->is_static() && (iid == vmIntrinsics::_compiledLambdaForm || - (MethodHandles::is_signature_polymorphic(iid) && MethodHandles::is_signature_polymorphic_intrinsic(iid))); - } bool return_oop = method->is_returning_oop(); - record_scope(next_pc_offset, stream, flags, true, is_mh_invoke, return_oop, JVMCI_CHECK); + record_scope(next_pc_offset, stream, flags, true, return_oop, JVMCI_CHECK); } else { record_scope(next_pc_offset, stream, flags, true, JVMCI_CHECK); } @@ -1339,9 +1333,6 @@ void CodeInstaller::site_Mark(CodeBuffer& buffer, jint pc_offset, HotSpotCompile case DEOPT_HANDLER_ENTRY: _offsets.set_value(CodeOffsets::Deopt, pc_offset); break; - case DEOPT_MH_HANDLER_ENTRY: - _offsets.set_value(CodeOffsets::DeoptMH, pc_offset); - break; case FRAME_COMPLETE: _offsets.set_value(CodeOffsets::Frame_Complete, pc_offset); break; @@ -1369,6 +1360,7 @@ void CodeInstaller::site_Mark(CodeBuffer& buffer, jint pc_offset, HotSpotCompile case VERIFY_OOP_BITS: case VERIFY_OOP_MASK: case VERIFY_OOP_COUNT_ADDRESS: + case DEOPT_MH_HANDLER_ENTRY: break; default: diff --git a/src/hotspot/share/jvmci/jvmciCodeInstaller.hpp b/src/hotspot/share/jvmci/jvmciCodeInstaller.hpp index a8279e99dc2..bdebed2d9e8 100644 --- a/src/hotspot/share/jvmci/jvmciCodeInstaller.hpp +++ b/src/hotspot/share/jvmci/jvmciCodeInstaller.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -411,10 +411,10 @@ protected: void record_oop_patch(HotSpotCompiledCodeStream* stream, address dest, u1 read_tag, bool narrow, JVMCI_TRAPS); // full_info: if false, only BytecodePosition is in stream otherwise all DebugInfo is in stream - void record_scope(jint pc_offset, HotSpotCompiledCodeStream* stream, u1 debug_info_flags, bool full_info, bool is_mh_invoke, bool return_oop, JVMCI_TRAPS); + void record_scope(jint pc_offset, HotSpotCompiledCodeStream* stream, u1 debug_info_flags, bool full_info, bool return_oop, JVMCI_TRAPS); void record_scope(jint pc_offset, HotSpotCompiledCodeStream* stream, u1 debug_info_flags, bool full_info, JVMCI_TRAPS) { - record_scope(pc_offset, stream, debug_info_flags, full_info, false /* is_mh_invoke */, false /* return_oop */, JVMCIENV); + record_scope(pc_offset, stream, debug_info_flags, full_info, false /* return_oop */, JVMCIENV); } void record_object_value(ObjectValue* sv, HotSpotCompiledCodeStream* stream, JVMCI_TRAPS); diff --git a/src/hotspot/share/jvmci/jvmciRuntime.cpp b/src/hotspot/share/jvmci/jvmciRuntime.cpp index e75527235f0..a178ac66344 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.cpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp @@ -228,9 +228,6 @@ extern void vm_exit(int code); // unpack_with_exception entry instead. This makes life for the exception blob easier // because making that same check and diverting is painful from assembly language. JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* current, oopDesc* ex, address pc, nmethod*& nm)) - // Reset method handle flag. - current->set_is_method_handle_return(false); - Handle exception(current, ex); // The frame we rethrow the exception to might not have been processed by the GC yet. @@ -305,8 +302,6 @@ JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* c if (guard_pages_enabled) { address fast_continuation = nm->handler_for_exception_and_pc(exception, pc); if (fast_continuation != nullptr) { - // Set flag if return address is a method handle call site. - current->set_is_method_handle_return(nm->is_method_handle_return(pc)); return fast_continuation; } } @@ -343,9 +338,6 @@ JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* c } } - // Set flag if return address is a method handle call site. - current->set_is_method_handle_return(nm->is_method_handle_return(pc)); - if (log_is_enabled(Info, exceptions)) { ResourceMark rm; log_info(exceptions)("Thread " PTR_FORMAT " continuing at PC " PTR_FORMAT diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index b91de1c9b35..b4f033a4f9a 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -242,7 +242,6 @@ nonstatic_field(JavaThread, _stack_overflow_state._stack_overflow_limit, address) \ volatile_nonstatic_field(JavaThread, _exception_oop, oop) \ volatile_nonstatic_field(JavaThread, _exception_pc, address) \ - volatile_nonstatic_field(JavaThread, _is_method_handle_return, int) \ volatile_nonstatic_field(JavaThread, _doing_unsafe_access, bool) \ nonstatic_field(JavaThread, _osthread, OSThread*) \ nonstatic_field(JavaThread, _saved_exception_pc, address) \ diff --git a/src/hotspot/share/opto/callGenerator.cpp b/src/hotspot/share/opto/callGenerator.cpp index e09d8cabe2c..03225044f5e 100644 --- a/src/hotspot/share/opto/callGenerator.cpp +++ b/src/hotspot/share/opto/callGenerator.cpp @@ -169,10 +169,6 @@ JVMState* DirectCallGenerator::generate(JVMState* jvms) { } // Mark the call node as virtual, sort of: call->set_optimized_virtual(true); - if (method()->is_method_handle_intrinsic() || - method()->is_compiled_lambda_form()) { - call->set_method_handle_invoke(true); - } } kit.set_arguments_for_java_call(call); kit.set_edges_for_java_call(call, false, _separate_io_proj); diff --git a/src/hotspot/share/opto/callnode.hpp b/src/hotspot/share/opto/callnode.hpp index 093c47194ef..9029a009989 100644 --- a/src/hotspot/share/opto/callnode.hpp +++ b/src/hotspot/share/opto/callnode.hpp @@ -778,7 +778,6 @@ protected: ciMethod* _method; // Method being direct called bool _optimized_virtual; - bool _method_handle_invoke; bool _override_symbolic_info; // Override symbolic call site info from bytecode bool _arg_escape; // ArgEscape in parameter list public: @@ -786,7 +785,6 @@ public: : CallNode(tf, addr, TypePtr::BOTTOM), _method(method), _optimized_virtual(false), - _method_handle_invoke(false), _override_symbolic_info(false), _arg_escape(false) { @@ -798,8 +796,6 @@ public: void set_method(ciMethod *m) { _method = m; } void set_optimized_virtual(bool f) { _optimized_virtual = f; } bool is_optimized_virtual() const { return _optimized_virtual; } - void set_method_handle_invoke(bool f) { _method_handle_invoke = f; } - bool is_method_handle_invoke() const { return _method_handle_invoke; } void set_override_symbolic_info(bool f) { _override_symbolic_info = f; } bool override_symbolic_info() const { return _override_symbolic_info; } void set_arg_escape(bool f) { _arg_escape = f; } diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index f828dfb6928..47de5acc2f2 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -650,7 +650,6 @@ Compile::Compile(ciEnv* ci_env, ciMethod* target, int osr_bci, _igv_idx(0), _trace_opto_output(directive->TraceOptoOutputOption), #endif - _has_method_handle_invokes(false), _clinit_barrier_on_entry(false), _stress_seed(0), _comp_arena(mtCompiler, Arena::Tag::tag_comp), @@ -925,7 +924,6 @@ Compile::Compile(ciEnv* ci_env, _igv_idx(0), _trace_opto_output(directive->TraceOptoOutputOption), #endif - _has_method_handle_invokes(false), _clinit_barrier_on_entry(false), _stress_seed(0), _comp_arena(mtCompiler, Arena::Tag::tag_comp), diff --git a/src/hotspot/share/opto/compile.hpp b/src/hotspot/share/opto/compile.hpp index 1cfcdca9610..05c5f22dad9 100644 --- a/src/hotspot/share/opto/compile.hpp +++ b/src/hotspot/share/opto/compile.hpp @@ -354,8 +354,6 @@ class Compile : public Phase { bool _parsed_irreducible_loop; // True if ciTypeFlow detected irreducible loops during parsing #endif bool _has_irreducible_loop; // Found irreducible loops - // JSR 292 - bool _has_method_handle_invokes; // True if this method has MethodHandle invokes. bool _has_monitors; // Metadata transfered to nmethod to enable Continuations lock-detection fastpath bool _has_scoped_access; // For shared scope closure bool _clinit_barrier_on_entry; // True if clinit barrier is needed on nmethod entry @@ -666,10 +664,6 @@ public: bool has_irreducible_loop() const { return _has_irreducible_loop; } void set_has_irreducible_loop(bool z) { _has_irreducible_loop = z; } - // JSR 292 - bool has_method_handle_invokes() const { return _has_method_handle_invokes; } - void set_has_method_handle_invokes(bool z) { _has_method_handle_invokes = z; } - Ticks _latest_stage_start_counter; void begin_method(); diff --git a/src/hotspot/share/opto/lcm.cpp b/src/hotspot/share/opto/lcm.cpp index ca1863b685e..fd7644f8587 100644 --- a/src/hotspot/share/opto/lcm.cpp +++ b/src/hotspot/share/opto/lcm.cpp @@ -946,17 +946,6 @@ uint PhaseCFG::sched_call(Block* block, uint node_cnt, Node_List& worklist, Grow // references but there no way to handle oops differently than other // pointers as far as the kill mask goes. bool exclude_soe = op == Op_CallRuntime; - - // If the call is a MethodHandle invoke, we need to exclude the - // register which is used to save the SP value over MH invokes from - // the mask. Otherwise this register could be used for - // deoptimization information. - if (op == Op_CallStaticJava) { - MachCallStaticJavaNode* mcallstaticjava = (MachCallStaticJavaNode*) mcall; - if (mcallstaticjava->_method_handle_invoke) - proj->_rout.OR(Matcher::method_handle_invoke_SP_save_mask()); - } - add_call_kills(proj, regs, save_policy, exclude_soe); return node_cnt; diff --git a/src/hotspot/share/opto/machnode.cpp b/src/hotspot/share/opto/machnode.cpp index e5acad98c09..5da929e4748 100644 --- a/src/hotspot/share/opto/machnode.cpp +++ b/src/hotspot/share/opto/machnode.cpp @@ -772,8 +772,6 @@ bool MachCallJavaNode::cmp( const Node &n ) const { } #ifndef PRODUCT void MachCallJavaNode::dump_spec(outputStream *st) const { - if (_method_handle_invoke) - st->print("MethodHandle "); if (_method) { _method->print_short_name(st); st->print(" "); @@ -794,10 +792,7 @@ const RegMask &MachCallJavaNode::in_RegMask(uint idx) const { } // Values outside the domain represent debug info Matcher* m = Compile::current()->matcher(); - // If this call is a MethodHandle invoke we have to use a different - // debugmask which does not include the register we use to save the - // SP over MH invokes. - RegMask** debugmask = _method_handle_invoke ? m->idealreg2mhdebugmask : m->idealreg2debugmask; + RegMask** debugmask = m->idealreg2debugmask; return *debugmask[in(idx)->ideal_reg()]; } diff --git a/src/hotspot/share/opto/machnode.hpp b/src/hotspot/share/opto/machnode.hpp index 5490f717a25..43e9a35df34 100644 --- a/src/hotspot/share/opto/machnode.hpp +++ b/src/hotspot/share/opto/machnode.hpp @@ -960,7 +960,6 @@ public: ciMethod* _method; // Method being direct called bool _override_symbolic_info; // Override symbolic call site info from bytecode bool _optimized_virtual; // Tells if node is a static call or an optimized virtual - bool _method_handle_invoke; // Tells if the call has to preserve SP bool _arg_escape; // ArgEscape in parameter list MachCallJavaNode() : MachCallNode(), _override_symbolic_info(false) { init_class_id(Class_MachCallJava); diff --git a/src/hotspot/share/opto/matcher.cpp b/src/hotspot/share/opto/matcher.cpp index b43bc05c465..7d73487cf88 100644 --- a/src/hotspot/share/opto/matcher.cpp +++ b/src/hotspot/share/opto/matcher.cpp @@ -50,8 +50,6 @@ const RegMask *Matcher::idealreg2regmask[_last_machine_leaf]; RegMask Matcher::mreg2regmask[_last_Mach_Reg]; RegMask Matcher::caller_save_regmask; RegMask Matcher::caller_save_regmask_exclude_soe; -RegMask Matcher::mh_caller_save_regmask; -RegMask Matcher::mh_caller_save_regmask_exclude_soe; RegMask Matcher::STACK_ONLY_mask; RegMask Matcher::c_frame_ptr_mask; const uint Matcher::_begin_rematerialize = _BEGIN_REMATERIALIZE; @@ -114,21 +112,6 @@ Matcher::Matcher() idealreg2debugmask [Op_RegFlags] = nullptr; idealreg2debugmask [Op_RegVectMask] = nullptr; - idealreg2mhdebugmask[Op_RegI] = nullptr; - idealreg2mhdebugmask[Op_RegN] = nullptr; - idealreg2mhdebugmask[Op_RegL] = nullptr; - idealreg2mhdebugmask[Op_RegF] = nullptr; - idealreg2mhdebugmask[Op_RegD] = nullptr; - idealreg2mhdebugmask[Op_RegP] = nullptr; - idealreg2mhdebugmask[Op_VecA] = nullptr; - idealreg2mhdebugmask[Op_VecS] = nullptr; - idealreg2mhdebugmask[Op_VecD] = nullptr; - idealreg2mhdebugmask[Op_VecX] = nullptr; - idealreg2mhdebugmask[Op_VecY] = nullptr; - idealreg2mhdebugmask[Op_VecZ] = nullptr; - idealreg2mhdebugmask[Op_RegFlags] = nullptr; - idealreg2mhdebugmask[Op_RegVectMask] = nullptr; - DEBUG_ONLY(_mem_node = nullptr;) // Ideal memory node consumed by mach node } @@ -465,7 +448,7 @@ int Matcher::scalable_predicate_reg_slots() { return round_up_power_of_2(slots); } -#define NOF_STACK_MASKS (3*13) +#define NOF_STACK_MASKS (2*13) // Create the initial stack mask used by values spilling to the stack. // Disallow any debug info in outgoing argument areas by setting the @@ -480,51 +463,12 @@ void Matcher::init_first_stack_mask() { new (rms + i) RegMask(C->comp_arena()); } - idealreg2spillmask [Op_RegN] = &rms[0]; - idealreg2spillmask [Op_RegI] = &rms[1]; - idealreg2spillmask [Op_RegL] = &rms[2]; - idealreg2spillmask [Op_RegF] = &rms[3]; - idealreg2spillmask [Op_RegD] = &rms[4]; - idealreg2spillmask [Op_RegP] = &rms[5]; - - idealreg2debugmask [Op_RegN] = &rms[6]; - idealreg2debugmask [Op_RegI] = &rms[7]; - idealreg2debugmask [Op_RegL] = &rms[8]; - idealreg2debugmask [Op_RegF] = &rms[9]; - idealreg2debugmask [Op_RegD] = &rms[10]; - idealreg2debugmask [Op_RegP] = &rms[11]; - - idealreg2mhdebugmask[Op_RegN] = &rms[12]; - idealreg2mhdebugmask[Op_RegI] = &rms[13]; - idealreg2mhdebugmask[Op_RegL] = &rms[14]; - idealreg2mhdebugmask[Op_RegF] = &rms[15]; - idealreg2mhdebugmask[Op_RegD] = &rms[16]; - idealreg2mhdebugmask[Op_RegP] = &rms[17]; - - idealreg2spillmask [Op_VecA] = &rms[18]; - idealreg2spillmask [Op_VecS] = &rms[19]; - idealreg2spillmask [Op_VecD] = &rms[20]; - idealreg2spillmask [Op_VecX] = &rms[21]; - idealreg2spillmask [Op_VecY] = &rms[22]; - idealreg2spillmask [Op_VecZ] = &rms[23]; - - idealreg2debugmask [Op_VecA] = &rms[24]; - idealreg2debugmask [Op_VecS] = &rms[25]; - idealreg2debugmask [Op_VecD] = &rms[26]; - idealreg2debugmask [Op_VecX] = &rms[27]; - idealreg2debugmask [Op_VecY] = &rms[28]; - idealreg2debugmask [Op_VecZ] = &rms[29]; - - idealreg2mhdebugmask[Op_VecA] = &rms[30]; - idealreg2mhdebugmask[Op_VecS] = &rms[31]; - idealreg2mhdebugmask[Op_VecD] = &rms[32]; - idealreg2mhdebugmask[Op_VecX] = &rms[33]; - idealreg2mhdebugmask[Op_VecY] = &rms[34]; - idealreg2mhdebugmask[Op_VecZ] = &rms[35]; - - idealreg2spillmask [Op_RegVectMask] = &rms[36]; - idealreg2debugmask [Op_RegVectMask] = &rms[37]; - idealreg2mhdebugmask[Op_RegVectMask] = &rms[38]; + int index = 0; + for (int i = Op_RegN; i <= Op_RegVectMask; ++i) { + idealreg2spillmask[i] = &rms[index++]; + idealreg2debugmask[i] = &rms[index++]; + } + assert(index == NOF_STACK_MASKS, "wrong size"); // At first, start with the empty mask C->FIRST_STACK_mask().Clear(); @@ -710,26 +654,10 @@ void Matcher::init_first_stack_mask() { *idealreg2debugmask [Op_VecY] = *idealreg2spillmask[Op_VecY]; *idealreg2debugmask [Op_VecZ] = *idealreg2spillmask[Op_VecZ]; - *idealreg2mhdebugmask[Op_RegN] = *idealreg2spillmask[Op_RegN]; - *idealreg2mhdebugmask[Op_RegI] = *idealreg2spillmask[Op_RegI]; - *idealreg2mhdebugmask[Op_RegL] = *idealreg2spillmask[Op_RegL]; - *idealreg2mhdebugmask[Op_RegF] = *idealreg2spillmask[Op_RegF]; - *idealreg2mhdebugmask[Op_RegD] = *idealreg2spillmask[Op_RegD]; - *idealreg2mhdebugmask[Op_RegP] = *idealreg2spillmask[Op_RegP]; - *idealreg2mhdebugmask[Op_RegVectMask] = *idealreg2spillmask[Op_RegVectMask]; - - *idealreg2mhdebugmask[Op_VecA] = *idealreg2spillmask[Op_VecA]; - *idealreg2mhdebugmask[Op_VecS] = *idealreg2spillmask[Op_VecS]; - *idealreg2mhdebugmask[Op_VecD] = *idealreg2spillmask[Op_VecD]; - *idealreg2mhdebugmask[Op_VecX] = *idealreg2spillmask[Op_VecX]; - *idealreg2mhdebugmask[Op_VecY] = *idealreg2spillmask[Op_VecY]; - *idealreg2mhdebugmask[Op_VecZ] = *idealreg2spillmask[Op_VecZ]; - // Prevent stub compilations from attempting to reference // callee-saved (SOE) registers from debug info bool exclude_soe = !Compile::current()->is_method_compilation(); RegMask* caller_save_mask = exclude_soe ? &caller_save_regmask_exclude_soe : &caller_save_regmask; - RegMask* mh_caller_save_mask = exclude_soe ? &mh_caller_save_regmask_exclude_soe : &mh_caller_save_regmask; idealreg2debugmask[Op_RegN]->SUBTRACT(*caller_save_mask); idealreg2debugmask[Op_RegI]->SUBTRACT(*caller_save_mask); @@ -745,21 +673,6 @@ void Matcher::init_first_stack_mask() { idealreg2debugmask[Op_VecX]->SUBTRACT(*caller_save_mask); idealreg2debugmask[Op_VecY]->SUBTRACT(*caller_save_mask); idealreg2debugmask[Op_VecZ]->SUBTRACT(*caller_save_mask); - - idealreg2mhdebugmask[Op_RegN]->SUBTRACT(*mh_caller_save_mask); - idealreg2mhdebugmask[Op_RegI]->SUBTRACT(*mh_caller_save_mask); - idealreg2mhdebugmask[Op_RegL]->SUBTRACT(*mh_caller_save_mask); - idealreg2mhdebugmask[Op_RegF]->SUBTRACT(*mh_caller_save_mask); - idealreg2mhdebugmask[Op_RegD]->SUBTRACT(*mh_caller_save_mask); - idealreg2mhdebugmask[Op_RegP]->SUBTRACT(*mh_caller_save_mask); - idealreg2mhdebugmask[Op_RegVectMask]->SUBTRACT(*mh_caller_save_mask); - - idealreg2mhdebugmask[Op_VecA]->SUBTRACT(*mh_caller_save_mask); - idealreg2mhdebugmask[Op_VecS]->SUBTRACT(*mh_caller_save_mask); - idealreg2mhdebugmask[Op_VecD]->SUBTRACT(*mh_caller_save_mask); - idealreg2mhdebugmask[Op_VecX]->SUBTRACT(*mh_caller_save_mask); - idealreg2mhdebugmask[Op_VecY]->SUBTRACT(*mh_caller_save_mask); - idealreg2mhdebugmask[Op_VecZ]->SUBTRACT(*mh_caller_save_mask); } //---------------------------is_save_on_entry---------------------------------- @@ -984,23 +897,15 @@ void Matcher::init_spill_mask( Node *ret ) { if (_register_save_policy[i] == 'C' || _register_save_policy[i] == 'A') { caller_save_regmask.Insert(i); - mh_caller_save_regmask.Insert(i); } // Exclude save-on-entry registers from debug masks for stub compilations. if (_register_save_policy[i] == 'C' || _register_save_policy[i] == 'A' || _register_save_policy[i] == 'E') { caller_save_regmask_exclude_soe.Insert(i); - mh_caller_save_regmask_exclude_soe.Insert(i); } } - // Also exclude the register we use to save the SP for MethodHandle - // invokes to from the corresponding MH debug masks - const RegMask sp_save_mask = method_handle_invoke_SP_save_mask(); - mh_caller_save_regmask.OR(sp_save_mask); - mh_caller_save_regmask_exclude_soe.OR(sp_save_mask); - // Grab the Frame Pointer Node *fp = ret->in(TypeFunc::FramePtr); // Share frame pointer while making spill ops @@ -1272,7 +1177,6 @@ MachNode *Matcher::match_sfpt( SafePointNode *sfpt ) { CallNode *call; const TypeTuple *domain; ciMethod* method = nullptr; - bool is_method_handle_invoke = false; // for special kill effects if( sfpt->is_Call() ) { call = sfpt->as_Call(); domain = call->tf()->domain(); @@ -1298,13 +1202,8 @@ MachNode *Matcher::match_sfpt( SafePointNode *sfpt ) { method = call_java->method(); mcall_java->_method = method; mcall_java->_optimized_virtual = call_java->is_optimized_virtual(); - is_method_handle_invoke = call_java->is_method_handle_invoke(); - mcall_java->_method_handle_invoke = is_method_handle_invoke; mcall_java->_override_symbolic_info = call_java->override_symbolic_info(); mcall_java->_arg_escape = call_java->arg_escape(); - if (is_method_handle_invoke) { - C->set_has_method_handle_invokes(true); - } if( mcall_java->is_MachCallStaticJava() ) mcall_java->as_MachCallStaticJava()->_name = call_java->as_CallStaticJava()->_name; diff --git a/src/hotspot/share/opto/matcher.hpp b/src/hotspot/share/opto/matcher.hpp index f4b0a7db873..0b609b70ab5 100644 --- a/src/hotspot/share/opto/matcher.hpp +++ b/src/hotspot/share/opto/matcher.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -177,7 +177,6 @@ public: static const RegMask *idealreg2regmask[]; RegMask *idealreg2spillmask [_last_machine_leaf]; RegMask *idealreg2debugmask [_last_machine_leaf]; - RegMask *idealreg2mhdebugmask[_last_machine_leaf]; void init_spill_mask( Node *ret ); // Convert machine register number to register mask static uint mreg2regmask_max; @@ -185,8 +184,6 @@ public: static RegMask STACK_ONLY_mask; static RegMask caller_save_regmask; static RegMask caller_save_regmask_exclude_soe; - static RegMask mh_caller_save_regmask; - static RegMask mh_caller_save_regmask_exclude_soe; MachNode* mach_null() const { return _mach_null; } @@ -424,8 +421,6 @@ public: // a code which use multiply for division by constant. static bool use_asm_for_ldiv_by_con( jlong divisor ); - static const RegMask method_handle_invoke_SP_save_mask(); - // Java-Interpreter calling convention // (what you use when calling between compiled-Java and Interpreted-Java diff --git a/src/hotspot/share/opto/output.cpp b/src/hotspot/share/opto/output.cpp index 90d24b609a7..84c01c68e38 100644 --- a/src/hotspot/share/opto/output.cpp +++ b/src/hotspot/share/opto/output.cpp @@ -992,7 +992,6 @@ void PhaseOutput::Process_OopMap_Node(MachNode *mach, int current_offset) { MachCallNode *mcall; int safepoint_pc_offset = current_offset; - bool is_method_handle_invoke = false; bool return_oop = false; bool has_ea_local_in_scope = sfn->_has_ea_local_in_scope; bool arg_escape = false; @@ -1004,12 +1003,7 @@ void PhaseOutput::Process_OopMap_Node(MachNode *mach, int current_offset) { } else { mcall = mach->as_MachCall(); - // Is the call a MethodHandle call? if (mcall->is_MachCallJava()) { - if (mcall->as_MachCallJava()->_method_handle_invoke) { - assert(C->has_method_handle_invokes(), "must have been set during call generation"); - is_method_handle_invoke = true; - } arg_escape = mcall->as_MachCallJava()->_arg_escape; } @@ -1192,7 +1186,6 @@ void PhaseOutput::Process_OopMap_Node(MachNode *mach, int current_offset) { jvms->bci(), jvms->should_reexecute(), rethrow_exception, - is_method_handle_invoke, return_oop, has_ea_local_in_scope, arg_escape, @@ -1370,9 +1363,6 @@ CodeBuffer* PhaseOutput::init_buffer() { exception_handler_req + deopt_handler_req; // deopt handler - if (C->has_method_handle_invokes()) - total_req += deopt_handler_req; // deopt MH handler - CodeBuffer* cb = code_buffer(); cb->set_const_section_alignment(constant_table().alignment()); cb->initialize(total_req, _buf_sizes._reloc); @@ -1806,13 +1796,6 @@ void PhaseOutput::fill_buffer(C2_MacroAssembler* masm, uint* blk_starts) { } // Emit the deopt handler code. _code_offsets.set_value(CodeOffsets::Deopt, HandlerImpl::emit_deopt_handler(masm)); - - // Emit the MethodHandle deopt handler code (if required). - if (C->has_method_handle_invokes() && !C->failing()) { - // We can use the same code as for the normal deopt handler, we - // just need a different entry point address. - _code_offsets.set_value(CodeOffsets::DeoptMH, HandlerImpl::emit_deopt_handler(masm)); - } } // One last check for failed CodeBuffer::expand: diff --git a/src/hotspot/share/opto/runtime.cpp b/src/hotspot/share/opto/runtime.cpp index 0d148edda6e..072b1384921 100644 --- a/src/hotspot/share/opto/runtime.cpp +++ b/src/hotspot/share/opto/runtime.cpp @@ -1913,9 +1913,6 @@ JRT_ENTRY_NO_ASYNC(address, OptoRuntime::handle_exception_C_helper(JavaThread* c current->set_exception_pc(pc); current->set_exception_handler_pc(handler_address); - - // Check if the exception PC is a MethodHandle call site. - current->set_is_method_handle_return(nm->is_method_handle_return(pc)); } // Restore correct return pc. Was saved above. diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp index a96c18a18aa..853c6554022 100644 --- a/src/hotspot/share/runtime/deoptimization.cpp +++ b/src/hotspot/share/runtime/deoptimization.cpp @@ -589,12 +589,7 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread // Verify we have the right vframeArray assert(cb->frame_size() >= 0, "Unexpected frame size"); intptr_t* unpack_sp = stub_frame.sp() + cb->frame_size(); - - // If the deopt call site is a MethodHandle invoke call site we have - // to adjust the unpack_sp. - nmethod* deoptee_nm = deoptee.cb()->as_nmethod_or_null(); - if (deoptee_nm != nullptr && deoptee_nm->is_method_handle_return(deoptee.pc())) - unpack_sp = deoptee.unextended_sp(); + assert(unpack_sp == deoptee.unextended_sp(), "must be"); #ifdef ASSERT assert(cb->is_deoptimization_stub() || diff --git a/src/hotspot/share/runtime/frame.cpp b/src/hotspot/share/runtime/frame.cpp index 75c6e388b0d..e578e614440 100644 --- a/src/hotspot/share/runtime/frame.cpp +++ b/src/hotspot/share/runtime/frame.cpp @@ -206,10 +206,7 @@ address frame::raw_pc() const { if (is_deoptimized_frame()) { nmethod* nm = cb()->as_nmethod_or_null(); assert(nm != nullptr, "only nmethod is expected here"); - if (nm->is_method_handle_return(pc())) - return nm->deopt_mh_handler_begin() - pc_return_offset; - else - return nm->deopt_handler_begin() - pc_return_offset; + return nm->deopt_handler_begin() - pc_return_offset; } else { return (pc() - pc_return_offset); } @@ -358,9 +355,7 @@ void frame::deoptimize(JavaThread* thread) { // If the call site is a MethodHandle call site use the MH deopt handler. nmethod* nm = _cb->as_nmethod(); - address deopt = nm->is_method_handle_return(pc()) ? - nm->deopt_mh_handler_begin() : - nm->deopt_handler_begin(); + address deopt = nm->deopt_handler_begin(); NativePostCallNop* inst = nativePostCallNop_at(pc()); diff --git a/src/hotspot/share/runtime/frame.inline.hpp b/src/hotspot/share/runtime/frame.inline.hpp index 449abddd443..cbf01dd5763 100644 --- a/src/hotspot/share/runtime/frame.inline.hpp +++ b/src/hotspot/share/runtime/frame.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -76,7 +76,10 @@ inline address frame::get_deopt_original_pc() const { nmethod* nm = _cb->as_nmethod_or_null(); if (nm != nullptr && nm->is_deopt_pc(_pc)) { - return nm->get_original_pc(this); + address original_pc = nm->get_original_pc(this); + assert(nm->insts_contains_inclusive(original_pc), + "original PC must be in the main code section of the compiled method (or must be immediately following it)"); + return original_pc; } return nullptr; } diff --git a/src/hotspot/share/runtime/javaThread.cpp b/src/hotspot/share/runtime/javaThread.cpp index f5cd43b1769..e5af8d7bedd 100644 --- a/src/hotspot/share/runtime/javaThread.cpp +++ b/src/hotspot/share/runtime/javaThread.cpp @@ -476,7 +476,6 @@ JavaThread::JavaThread(MemTag mem_tag) : _exception_oop(oop()), _exception_pc(nullptr), _exception_handler_pc(nullptr), - _is_method_handle_return(0), _jni_active_critical(0), _pending_jni_exception_check_fn(nullptr), diff --git a/src/hotspot/share/runtime/javaThread.hpp b/src/hotspot/share/runtime/javaThread.hpp index 00bc5969196..89c3191669a 100644 --- a/src/hotspot/share/runtime/javaThread.hpp +++ b/src/hotspot/share/runtime/javaThread.hpp @@ -450,7 +450,6 @@ class JavaThread: public Thread { volatile oop _exception_oop; // Exception thrown in compiled code volatile address _exception_pc; // PC where exception happened volatile address _exception_handler_pc; // PC for handler of exception - volatile int _is_method_handle_return; // true (== 1) if the current exception PC is a MethodHandle call site. private: // support for JNI critical regions @@ -817,7 +816,6 @@ public: void set_exception_oop(oop o); void set_exception_pc(address a) { _exception_pc = a; } void set_exception_handler_pc(address a) { _exception_handler_pc = a; } - void set_is_method_handle_return(bool value) { _is_method_handle_return = value ? 1 : 0; } void clear_exception_oop_and_pc() { set_exception_oop(nullptr); @@ -866,7 +864,6 @@ public: static ByteSize exception_oop_offset() { return byte_offset_of(JavaThread, _exception_oop); } static ByteSize exception_pc_offset() { return byte_offset_of(JavaThread, _exception_pc); } static ByteSize exception_handler_pc_offset() { return byte_offset_of(JavaThread, _exception_handler_pc); } - static ByteSize is_method_handle_return_offset() { return byte_offset_of(JavaThread, _is_method_handle_return); } static ByteSize active_handles_offset() { return byte_offset_of(JavaThread, _active_handles); } diff --git a/src/hotspot/share/runtime/sharedRuntime.cpp b/src/hotspot/share/runtime/sharedRuntime.cpp index c3a6e0a4dc3..c81c975372c 100644 --- a/src/hotspot/share/runtime/sharedRuntime.cpp +++ b/src/hotspot/share/runtime/sharedRuntime.cpp @@ -525,9 +525,6 @@ address SharedRuntime::raw_exception_handler_for_return_address(JavaThread* curr assert(frame::verify_return_pc(return_address), "must be a return address: " INTPTR_FORMAT, p2i(return_address)); assert(current->frames_to_pop_failed_realloc() == 0 || Interpreter::contains(return_address), "missed frames to pop?"); - // Reset method handle flag. - current->set_is_method_handle_return(false); - #if INCLUDE_JVMCI // JVMCI's ExceptionHandlerStub expects the thread local exception PC to be clear // and other exception handler continuations do not read it @@ -542,8 +539,6 @@ address SharedRuntime::raw_exception_handler_for_return_address(JavaThread* curr CodeBlob* blob = CodeCache::find_blob(return_address); nmethod* nm = (blob != nullptr) ? blob->as_nmethod_or_null() : nullptr; if (nm != nullptr) { - // Set flag if return address is a method handle call site. - current->set_is_method_handle_return(nm->is_method_handle_return(return_address)); // native nmethods don't have exception handlers assert(!nm->is_native_method() || nm->method()->is_continuation_enter_intrinsic(), "no exception handler"); assert(nm->header_begin() != nm->exception_begin(), "no exception handler"); diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index 5a3850feac8..dee0a5d4eb7 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -536,7 +536,6 @@ nonstatic_field(nmethod, _state, volatile signed char) \ nonstatic_field(nmethod, _exception_offset, int) \ nonstatic_field(nmethod, _deopt_handler_offset, int) \ - nonstatic_field(nmethod, _deopt_mh_handler_offset, int) \ nonstatic_field(nmethod, _orig_pc_offset, int) \ nonstatic_field(nmethod, _stub_offset, int) \ nonstatic_field(nmethod, _scopes_pcs_offset, int) \ @@ -608,7 +607,6 @@ volatile_nonstatic_field(JavaThread, _suspend_flags, uint32_t) \ volatile_nonstatic_field(JavaThread, _exception_oop, oop) \ volatile_nonstatic_field(JavaThread, _exception_pc, address) \ - volatile_nonstatic_field(JavaThread, _is_method_handle_return, int) \ nonstatic_field(JavaThread, _saved_exception_pc, address) \ volatile_nonstatic_field(JavaThread, _thread_state, JavaThreadState) \ nonstatic_field(JavaThread, _stack_base, address) \ @@ -1711,7 +1709,6 @@ /**********************/ \ \ declare_constant(PcDesc::PCDESC_reexecute) \ - declare_constant(PcDesc::PCDESC_is_method_handle_invoke) \ declare_constant(PcDesc::PCDESC_return_oop) \ \ /**********************/ \ diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/NMethod.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/NMethod.java index a3228765e91..c8ba2e8b5af 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/NMethod.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/NMethod.java @@ -48,7 +48,6 @@ public class NMethod extends CodeBlob { /** Offsets for different nmethod parts */ private static CIntegerField exceptionOffsetField; private static CIntegerField deoptHandlerOffsetField; - private static CIntegerField deoptMhHandlerOffsetField; private static CIntegerField origPCOffsetField; private static CIntegerField stubOffsetField; private static CIntField handlerTableOffsetField; @@ -86,7 +85,6 @@ public class NMethod extends CodeBlob { immutableDataSizeField = type.getCIntegerField("_immutable_data_size"); exceptionOffsetField = type.getCIntegerField("_exception_offset"); deoptHandlerOffsetField = type.getCIntegerField("_deopt_handler_offset"); - deoptMhHandlerOffsetField = type.getCIntegerField("_deopt_mh_handler_offset"); origPCOffsetField = type.getCIntegerField("_orig_pc_offset"); stubOffsetField = type.getCIntegerField("_stub_offset"); scopesPCsOffsetField = type.getCIntegerField("_scopes_pcs_offset"); @@ -125,7 +123,6 @@ public class NMethod extends CodeBlob { public Address instsEnd() { return headerBegin().addOffsetTo(getStubOffset()); } public Address exceptionBegin() { return headerBegin().addOffsetTo(getExceptionOffset()); } public Address deoptHandlerBegin() { return headerBegin().addOffsetTo(getDeoptHandlerOffset()); } - public Address deoptMhHandlerBegin() { return headerBegin().addOffsetTo(getDeoptMhHandlerOffset()); } public Address stubBegin() { return headerBegin().addOffsetTo(getStubOffset()); } public Address stubEnd() { return dataBegin(); } public Address oopsBegin() { return dataBegin(); } @@ -250,22 +247,10 @@ public class NMethod extends CodeBlob { return VMObjectFactory.newObject(NMethod.class, osrLinkField.getValue(addr)); } - // MethodHandle - public boolean isMethodHandleReturn(Address returnPc) { - // Hard to read a bit fields from Java and it's only there for performance - // so just go directly to the PCDesc - // if (!hasMethodHandleInvokes()) return false; - PCDesc pd = getPCDescAt(returnPc); - if (pd == null) - return false; - return pd.isMethodHandleInvoke(); - } - // Deopt // Return true is the PC is one would expect if the frame is being deopted. - public boolean isDeoptPc (Address pc) { return isDeoptEntry(pc) || isDeoptMhEntry(pc); } + public boolean isDeoptPc (Address pc) { return isDeoptEntry(pc); } public boolean isDeoptEntry (Address pc) { return pc == deoptHandlerBegin(); } - public boolean isDeoptMhEntry (Address pc) { return pc == deoptMhHandlerBegin(); } /** Tells whether frames described by this nmethod can be deoptimized. Note: native wrappers cannot be deoptimized. */ @@ -494,7 +479,6 @@ public class NMethod extends CodeBlob { private int getEntryBCI() { return (int) entryBCIField .getValue(addr); } private int getExceptionOffset() { return (int) exceptionOffsetField .getValue(addr); } private int getDeoptHandlerOffset() { return (int) deoptHandlerOffsetField .getValue(addr); } - private int getDeoptMhHandlerOffset() { return (int) deoptMhHandlerOffsetField.getValue(addr); } private int getStubOffset() { return (int) stubOffsetField .getValue(addr); } private int getScopesDataOffset() { return (int) scopesDataOffsetField .getValue(addr); } private int getScopesPCsOffset() { return (int) scopesPCsOffsetField .getValue(addr); } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/PCDesc.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/PCDesc.java index 58f358c01aa..037c26b53f5 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/PCDesc.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/PCDesc.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,7 +41,6 @@ public class PCDesc extends VMObject { private static CIntegerField objDecodeOffsetField; private static CIntegerField pcFlagsField; private static int reexecuteMask; - private static int isMethodHandleInvokeMask; private static int returnOopMask; static { @@ -61,7 +60,6 @@ public class PCDesc extends VMObject { pcFlagsField = type.getCIntegerField("_flags"); reexecuteMask = db.lookupIntConstant("PcDesc::PCDESC_reexecute"); - isMethodHandleInvokeMask = db.lookupIntConstant("PcDesc::PCDESC_is_method_handle_invoke"); returnOopMask = db.lookupIntConstant("PcDesc::PCDESC_return_oop"); } @@ -93,11 +91,6 @@ public class PCDesc extends VMObject { return (flags & reexecuteMask) != 0; } - public boolean isMethodHandleInvoke() { - int flags = (int)pcFlagsField.getValue(addr); - return (flags & isMethodHandleInvokeMask) != 0; - } - public void print(NMethod code) { printOn(System.out, code); } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Frame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Frame.java index a8c17a9f59e..27efb631f79 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Frame.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/Frame.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -81,6 +81,24 @@ public abstract class Frame implements Cloneable { return pcReturnOffset; } + protected void adjustForDeopt() { + if (pc != null) { + // Look for a deopt pc and if it is deopted convert to original pc + CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc); + if (cb != null && cb.isJavaMethod()) { + NMethod nm = (NMethod) cb; + if (pc.equals(nm.deoptHandlerBegin())) { + if (Assert.ASSERTS_ENABLED) { + Assert.that(this.getUnextendedSP() != null, "null SP in Java frame"); + } + // adjust pc if frame is deoptimized. + pc = this.getUnextendedSP().getAddressAt(nm.origPCOffset()); + deoptimized = true; + } + } + } + } + private static synchronized void initialize(TypeDataBase db) { Type ConstMethodType = db.lookupType("ConstMethod"); // FIXME: not sure whether alignment here is correct or how to diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/aarch64/AARCH64Frame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/aarch64/AARCH64Frame.java index dca5f2efa3b..a5aa7ce4405 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/aarch64/AARCH64Frame.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/aarch64/AARCH64Frame.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2019, Red Hat Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -106,30 +106,11 @@ public class AARCH64Frame extends Frame { private AARCH64Frame() { } - private void adjustForDeopt() { - if ( pc != null) { - // Look for a deopt pc and if it is deopted convert to original pc - CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc); - if (cb != null && cb.isJavaMethod()) { - NMethod nm = (NMethod) cb; - if (pc.equals(nm.deoptHandlerBegin())) { - if (Assert.ASSERTS_ENABLED) { - Assert.that(this.getUnextendedSP() != null, "null SP in Java frame"); - } - // adjust pc if frame is deoptimized. - pc = this.getUnextendedSP().getAddressAt(nm.origPCOffset()); - deoptimized = true; - } - } - } - } - public AARCH64Frame(Address raw_sp, Address raw_fp, Address pc) { this.raw_sp = raw_sp; this.raw_unextendedSP = raw_sp; this.raw_fp = raw_fp; this.pc = pc; - adjustUnextendedSP(); // Frame must be fully constructed before this call adjustForDeopt(); @@ -153,8 +134,6 @@ public class AARCH64Frame extends Frame { this.pc = savedPC; } - adjustUnextendedSP(); - // Frame must be fully constructed before this call adjustForDeopt(); @@ -169,7 +148,6 @@ public class AARCH64Frame extends Frame { this.raw_unextendedSP = raw_unextendedSp; this.raw_fp = raw_fp; this.pc = pc; - adjustUnextendedSP(); // Frame must be fully constructed before this call adjustForDeopt(); @@ -355,24 +333,6 @@ public class AARCH64Frame extends Frame { return fr; } - //------------------------------------------------------------------------------ - // frame::adjust_unextended_sp - private void adjustUnextendedSP() { - // Sites calling method handle intrinsics and lambda forms are - // treated as any other call site. Therefore, no special action is - // needed when we are returning to any of these call sites. - - CodeBlob cb = cb(); - NMethod senderNm = (cb == null) ? null : cb.asNMethodOrNull(); - if (senderNm != null) { - // If the sender PC is a deoptimization point, get the original PC. - if (senderNm.isDeoptEntry(getPC()) || - senderNm.isDeoptMhEntry(getPC())) { - // DEBUG_ONLY(verifyDeoptriginalPc(senderNm, raw_unextendedSp)); - } - } - } - private Frame senderForInterpreterFrame(AARCH64RegisterMap map) { if (DEBUG) { System.out.println("senderForInterpreterFrame"); diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ppc64/PPC64Frame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ppc64/PPC64Frame.java index a47a632c286..f4ce5337e2f 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ppc64/PPC64Frame.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ppc64/PPC64Frame.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -85,24 +85,6 @@ public class PPC64Frame extends Frame { private PPC64Frame() { } - private void adjustForDeopt() { - if ( pc != null) { - // Look for a deopt pc and if it is deopted convert to original pc - CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc); - if (cb != null && cb.isJavaMethod()) { - NMethod nm = (NMethod) cb; - if (pc.equals(nm.deoptHandlerBegin())) { - if (Assert.ASSERTS_ENABLED) { - Assert.that(this.getUnextendedSP() != null, "null SP in Java frame"); - } - // adjust pc if frame is deoptimized. - pc = this.getUnextendedSP().getAddressAt(nm.origPCOffset()); - deoptimized = true; - } - } - } - } - public PPC64Frame(Address raw_sp, Address raw_fp, Address pc) { this.raw_sp = raw_sp; this.raw_unextendedSP = raw_sp; @@ -116,7 +98,6 @@ public class PPC64Frame extends Frame { } else { this.pc = pc; } - adjustUnextendedSP(); // Frame must be fully constructed before this call adjustForDeopt(); @@ -136,7 +117,6 @@ public class PPC64Frame extends Frame { this.raw_fp = raw_fp; } this.pc = raw_sp.getAddressAt(2 * VM.getVM().getAddressSize()); - adjustUnextendedSP(); // Frame must be fully constructed before this call adjustForDeopt(); @@ -160,7 +140,6 @@ public class PPC64Frame extends Frame { } else { this.pc = pc; } - adjustUnextendedSP(); // Frame must be fully constructed before this call adjustForDeopt(); @@ -342,12 +321,6 @@ public class PPC64Frame extends Frame { return fr; } - //------------------------------------------------------------------------------ - // frame::adjust_unextended_sp - private void adjustUnextendedSP() { - // Nothing to do. senderForInterpreterFrame finds the correct unextendedSP. - } - private Frame senderForInterpreterFrame(PPC64RegisterMap map) { if (DEBUG) { System.out.println("senderForInterpreterFrame"); diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64Frame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64Frame.java index 948a3008016..e02e056f028 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64Frame.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64Frame.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2019, Red Hat Inc. * Copyright (c) 2021, 2023, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -101,30 +101,11 @@ public class RISCV64Frame extends Frame { private RISCV64Frame() { } - private void adjustForDeopt() { - if ( pc != null) { - // Look for a deopt pc and if it is deopted convert to original pc - CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc); - if (cb != null && cb.isJavaMethod()) { - NMethod nm = (NMethod) cb; - if (pc.equals(nm.deoptHandlerBegin())) { - if (Assert.ASSERTS_ENABLED) { - Assert.that(this.getUnextendedSP() != null, "null SP in Java frame"); - } - // adjust pc if frame is deoptimized. - pc = this.getUnextendedSP().getAddressAt(nm.origPCOffset()); - deoptimized = true; - } - } - } - } - public RISCV64Frame(Address raw_sp, Address raw_fp, Address pc) { this.raw_sp = raw_sp; this.raw_unextendedSP = raw_sp; this.raw_fp = raw_fp; this.pc = pc; - adjustUnextendedSP(); // Frame must be fully constructed before this call adjustForDeopt(); @@ -148,8 +129,6 @@ public class RISCV64Frame extends Frame { this.pc = savedPC; } - adjustUnextendedSP(); - // Frame must be fully constructed before this call adjustForDeopt(); @@ -164,7 +143,6 @@ public class RISCV64Frame extends Frame { this.raw_unextendedSP = raw_unextendedSp; this.raw_fp = raw_fp; this.pc = pc; - adjustUnextendedSP(); // Frame must be fully constructed before this call adjustForDeopt(); @@ -347,24 +325,6 @@ public class RISCV64Frame extends Frame { return fr; } - //------------------------------------------------------------------------------ - // frame::adjust_unextended_sp - private void adjustUnextendedSP() { - // Sites calling method handle intrinsics and lambda forms are - // treated as any other call site. Therefore, no special action is - // needed when we are returning to any of these call sites. - - CodeBlob cb = cb(); - NMethod senderNm = (cb == null) ? null : cb.asNMethodOrNull(); - if (senderNm != null) { - // If the sender PC is a deoptimization point, get the original PC. - if (senderNm.isDeoptEntry(getPC()) || - senderNm.isDeoptMhEntry(getPC())) { - // DEBUG_ONLY(verifyDeoptriginalPc(senderNm, raw_unextendedSp)); - } - } - } - private Frame senderForInterpreterFrame(RISCV64RegisterMap map) { if (DEBUG) { System.out.println("senderForInterpreterFrame"); diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java index 169ecea1565..3ee4f0a8158 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -102,24 +102,6 @@ public class X86Frame extends Frame { private X86Frame() { } - private void adjustForDeopt() { - if ( pc != null) { - // Look for a deopt pc and if it is deopted convert to original pc - CodeBlob cb = VM.getVM().getCodeCache().findBlob(pc); - if (cb != null && cb.isJavaMethod()) { - NMethod nm = (NMethod) cb; - if (pc.equals(nm.deoptHandlerBegin())) { - if (Assert.ASSERTS_ENABLED) { - Assert.that(this.getUnextendedSP() != null, "null SP in Java frame"); - } - // adjust pc if frame is deoptimized. - pc = this.getUnextendedSP().getAddressAt(nm.origPCOffset()); - deoptimized = true; - } - } - } - } - private void initFrame(Address raw_sp, Address raw_fp, Address pc, Address raw_unextendedSp, Address live_bcp) { this.raw_sp = raw_sp; this.raw_fp = raw_fp; @@ -134,11 +116,10 @@ public class X86Frame extends Frame { this.pc = pc; } this.live_bcp = live_bcp; - adjustUnextendedSP(); // Frame must be fully constructed before this call adjustForDeopt(); -} + } public X86Frame(Address raw_sp, Address raw_fp, Address pc) { @@ -352,24 +333,6 @@ public class X86Frame extends Frame { return fr; } - //------------------------------------------------------------------------------ - // frame::adjust_unextended_sp - private void adjustUnextendedSP() { - // On x86, sites calling method handle intrinsics and lambda forms are treated - // as any other call site. Therefore, no special action is needed when we are - // returning to any of these call sites. - - CodeBlob cb = cb(); - NMethod senderNm = (cb == null) ? null : cb.asNMethodOrNull(); - if (senderNm != null) { - // If the sender PC is a deoptimization point, get the original PC. - if (senderNm.isDeoptEntry(getPC()) || - senderNm.isDeoptMhEntry(getPC())) { - // DEBUG_ONLY(verifyDeoptriginalPc(senderNm, raw_unextendedSp)); - } - } - } - private Frame senderForInterpreterFrame(X86RegisterMap map) { if (DEBUG) { System.out.println("senderForInterpreterFrame"); From 854b384b120fa2af41adca3048070866fe3cafd4 Mon Sep 17 00:00:00 2001 From: Alex Menkov Date: Thu, 2 Oct 2025 23:39:37 +0000 Subject: [PATCH 0046/1639] 8304811: vmTestbase/vm/mlvm/indy/func/jvmti/stepBreakPopReturn/INDIFY_Test.java fails with JVMTI_ERROR_TYPE_MISMATCH Reviewed-by: lmesnik, dholmes, sspitsyn --- .../func/jvmti/stepBreakPopReturn/stepBreakPopReturn.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/hotspot/jtreg/vmTestbase/vm/mlvm/indy/func/jvmti/stepBreakPopReturn/stepBreakPopReturn.cpp b/test/hotspot/jtreg/vmTestbase/vm/mlvm/indy/func/jvmti/stepBreakPopReturn/stepBreakPopReturn.cpp index 413450892a5..0f7d1826937 100644 --- a/test/hotspot/jtreg/vmTestbase/vm/mlvm/indy/func/jvmti/stepBreakPopReturn/stepBreakPopReturn.cpp +++ b/test/hotspot/jtreg/vmTestbase/vm/mlvm/indy/func/jvmti/stepBreakPopReturn/stepBreakPopReturn.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -89,7 +89,7 @@ MethodEntry(jvmtiEnv *jvmti_env, gIsMethodEntryWorking = JNI_TRUE; if (!gIsBreakpointSet) - NSK_JVMTI_VERIFY(jvmti_env->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_SINGLE_STEP, nullptr)); + NSK_JVMTI_VERIFY(jvmti_env->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_SINGLE_STEP, thread)); } } @@ -116,7 +116,7 @@ SingleStep(jvmtiEnv *jvmti_env, free(locStr); } - NSK_JVMTI_VERIFY(gJvmtiEnv->SetEventNotificationMode(JVMTI_DISABLE, JVMTI_EVENT_SINGLE_STEP, nullptr)); + NSK_JVMTI_VERIFY(gJvmtiEnv->SetEventNotificationMode(JVMTI_DISABLE, JVMTI_EVENT_SINGLE_STEP, thread)); if (!gIsDebuggerCompatible) { if (!NSK_JVMTI_VERIFY(jvmti_env->SetBreakpoint(method, location))) From f62b9eca08694bbbe80d9e7d7b704db4f2423830 Mon Sep 17 00:00:00 2001 From: Ashutosh Mehra Date: Fri, 3 Oct 2025 02:43:14 +0000 Subject: [PATCH 0047/1639] 8364929: Assign unique id to each AdapterBlob stored in AOTCodeCache Reviewed-by: kvn, iklam --- src/hotspot/share/runtime/sharedRuntime.cpp | 35 ++++++++++++++------- src/hotspot/share/runtime/sharedRuntime.hpp | 14 ++++++--- 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/src/hotspot/share/runtime/sharedRuntime.cpp b/src/hotspot/share/runtime/sharedRuntime.cpp index c81c975372c..cf949fe1e7c 100644 --- a/src/hotspot/share/runtime/sharedRuntime.cpp +++ b/src/hotspot/share/runtime/sharedRuntime.cpp @@ -2515,6 +2515,7 @@ ArchivedAdapterTable AdapterHandlerLibrary::_aot_adapter_handler_table; #endif // INCLUDE_CDS static const int AdapterHandlerLibrary_size = 16*K; BufferBlob* AdapterHandlerLibrary::_buffer = nullptr; +volatile uint AdapterHandlerLibrary::_id_counter = 0; BufferBlob* AdapterHandlerLibrary::buffer_blob() { assert(_buffer != nullptr, "should be initialized"); @@ -2595,7 +2596,9 @@ void AdapterHandlerLibrary::initialize() { } AdapterHandlerEntry* AdapterHandlerLibrary::new_entry(AdapterFingerPrint* fingerprint) { - return AdapterHandlerEntry::allocate(fingerprint); + uint id = (uint)AtomicAccess::add((int*)&_id_counter, 1); + assert(id > 0, "we can never overflow because AOT cache cannot contain more than 2^32 methods"); + return AdapterHandlerEntry::allocate(id, fingerprint); } AdapterHandlerEntry* AdapterHandlerLibrary::get_simple_adapter(const methodHandle& method) { @@ -2749,8 +2752,8 @@ AdapterHandlerEntry* AdapterHandlerLibrary::get_adapter(const methodHandle& meth void AdapterHandlerLibrary::lookup_aot_cache(AdapterHandlerEntry* handler) { ResourceMark rm; - const char* name = AdapterHandlerLibrary::name(handler->fingerprint()); - const uint32_t id = AdapterHandlerLibrary::id(handler->fingerprint()); + const char* name = AdapterHandlerLibrary::name(handler); + const uint32_t id = AdapterHandlerLibrary::id(handler); CodeBlob* blob = AOTCodeCache::load_code_blob(AOTCodeEntry::Adapter, id, name); if (blob != nullptr) { @@ -2845,8 +2848,8 @@ bool AdapterHandlerLibrary::generate_adapter_code(AdapterHandlerEntry* handler, handler->set_adapter_blob(adapter_blob); if (!is_transient && AOTCodeCache::is_dumping_adapter()) { // try to save generated code - const char* name = AdapterHandlerLibrary::name(handler->fingerprint()); - const uint32_t id = AdapterHandlerLibrary::id(handler->fingerprint()); + const char* name = AdapterHandlerLibrary::name(handler); + const uint32_t id = AdapterHandlerLibrary::id(handler); bool success = AOTCodeCache::store_code_blob(*adapter_blob, AOTCodeEntry::Adapter, id, name); assert(success || !AOTCodeCache::is_dumping_adapter(), "caching of adapter must be disabled"); } @@ -2986,11 +2989,22 @@ void AdapterHandlerEntry::link() { } void AdapterHandlerLibrary::link_aot_adapters() { + uint max_id = 0; assert(AOTCodeCache::is_using_adapter(), "AOT adapters code should be available"); - _aot_adapter_handler_table.iterate([](AdapterHandlerEntry* entry) { + /* It is possible that some adapters generated in assembly phase are not stored in the cache. + * That implies adapter ids of the adapters in the cache may not be contiguous. + * If the size of the _aot_adapter_handler_table is used to initialize _id_counter, then it may + * result in collision of adapter ids between AOT stored handlers and runtime generated handlers. + * To avoid such situation, initialize the _id_counter with the largest adapter id among the AOT stored handlers. + */ + _aot_adapter_handler_table.iterate([&](AdapterHandlerEntry* entry) { assert(!entry->is_linked(), "AdapterHandlerEntry is already linked!"); entry->link(); + max_id = MAX2(max_id, entry->id()); }); + // Set adapter id to the maximum id found in the AOTCache + assert(_id_counter == 0, "Did not expect new AdapterHandlerEntry to be created at this stage"); + _id_counter = max_id; } // This method is called during production run to lookup simple adapters @@ -3355,13 +3369,12 @@ bool AdapterHandlerLibrary::contains(const CodeBlob* b) { return found; } -const char* AdapterHandlerLibrary::name(AdapterFingerPrint* fingerprint) { - return fingerprint->as_basic_args_string(); +const char* AdapterHandlerLibrary::name(AdapterHandlerEntry* handler) { + return handler->fingerprint()->as_basic_args_string(); } -uint32_t AdapterHandlerLibrary::id(AdapterFingerPrint* fingerprint) { - unsigned int hash = fingerprint->compute_hash(); - return hash; +uint32_t AdapterHandlerLibrary::id(AdapterHandlerEntry* handler) { + return handler->id(); } void AdapterHandlerLibrary::print_handler_on(outputStream* st, const CodeBlob* b) { diff --git a/src/hotspot/share/runtime/sharedRuntime.hpp b/src/hotspot/share/runtime/sharedRuntime.hpp index 374985ad921..6544e380d99 100644 --- a/src/hotspot/share/runtime/sharedRuntime.hpp +++ b/src/hotspot/share/runtime/sharedRuntime.hpp @@ -686,6 +686,7 @@ class AdapterHandlerEntry : public MetaspaceObj { private: AdapterFingerPrint* _fingerprint; AdapterBlob* _adapter_blob; + uint _id; bool _linked; static const char *_entry_names[]; @@ -697,9 +698,10 @@ class AdapterHandlerEntry : public MetaspaceObj { int _saved_code_length; #endif - AdapterHandlerEntry(AdapterFingerPrint* fingerprint) : + AdapterHandlerEntry(int id, AdapterFingerPrint* fingerprint) : _fingerprint(fingerprint), _adapter_blob(nullptr), + _id(id), _linked(false) #ifdef ASSERT , _saved_code(nullptr), @@ -720,8 +722,8 @@ class AdapterHandlerEntry : public MetaspaceObj { } public: - static AdapterHandlerEntry* allocate(AdapterFingerPrint* fingerprint) { - return new(0) AdapterHandlerEntry(fingerprint); + static AdapterHandlerEntry* allocate(uint id, AdapterFingerPrint* fingerprint) { + return new(0) AdapterHandlerEntry(id, fingerprint); } static void deallocate(AdapterHandlerEntry *handler) { @@ -772,6 +774,7 @@ class AdapterHandlerEntry : public MetaspaceObj { AdapterBlob* adapter_blob() const { return _adapter_blob; } bool is_linked() const { return _linked; } + uint id() const { return _id; } AdapterFingerPrint* fingerprint() const { return _fingerprint; } #ifdef ASSERT @@ -798,6 +801,7 @@ class ArchivedAdapterTable; class AdapterHandlerLibrary: public AllStatic { friend class SharedRuntime; private: + static volatile uint _id_counter; // counter for generating unique adapter ids, range = [1,UINT_MAX] static BufferBlob* _buffer; // the temporary code buffer in CodeCache static AdapterHandlerEntry* _no_arg_handler; static AdapterHandlerEntry* _int_arg_handler; @@ -837,8 +841,8 @@ class AdapterHandlerLibrary: public AllStatic { static void print_handler(const CodeBlob* b) { print_handler_on(tty, b); } static void print_handler_on(outputStream* st, const CodeBlob* b); static bool contains(const CodeBlob* b); - static const char* name(AdapterFingerPrint* fingerprint); - static uint32_t id(AdapterFingerPrint* fingerprint); + static const char* name(AdapterHandlerEntry* handler); + static uint32_t id(AdapterHandlerEntry* handler); #ifndef PRODUCT static void print_statistics(); #endif // PRODUCT From 3790965df3e7cba3b9792b8719d1e2ead046da15 Mon Sep 17 00:00:00 2001 From: Joe Wang Date: Fri, 3 Oct 2025 03:50:01 +0000 Subject: [PATCH 0048/1639] 8336695: Update Commons BCEL to Version 6.10.0 Reviewed-by: lancea, naoto, iris --- .../sun/org/apache/bcel/internal/Const.java | 828 ++++++++++-------- .../apache/bcel/internal/ExceptionConst.java | 7 +- .../org/apache/bcel/internal/Repository.java | 6 +- .../bcel/internal/classfile/AccessFlags.java | 232 ++++- .../internal/classfile/AnnotationEntry.java | 15 +- .../bcel/internal/classfile/Annotations.java | 10 +- .../internal/classfile/ArrayElementValue.java | 4 +- .../bcel/internal/classfile/Attribute.java | 8 +- .../internal/classfile/BootstrapMethod.java | 15 +- .../internal/classfile/BootstrapMethods.java | 6 +- .../classfile/ClassFormatException.java | 10 +- .../bcel/internal/classfile/ClassParser.java | 12 +- .../apache/bcel/internal/classfile/Code.java | 45 +- .../internal/classfile/CodeException.java | 8 +- .../bcel/internal/classfile/Constant.java | 31 +- .../bcel/internal/classfile/ConstantCP.java | 12 +- .../internal/classfile/ConstantDouble.java | 6 +- .../internal/classfile/ConstantFloat.java | 6 +- .../internal/classfile/ConstantInteger.java | 6 +- .../bcel/internal/classfile/ConstantLong.java | 6 +- .../internal/classfile/ConstantObject.java | 7 +- .../bcel/internal/classfile/ConstantPool.java | 29 +- .../bcel/internal/classfile/ConstantUtf8.java | 23 +- .../internal/classfile/ConstantValue.java | 2 +- .../bcel/internal/classfile/Deprecated.java | 2 +- .../internal/classfile/DescendingVisitor.java | 41 +- .../bcel/internal/classfile/ElementValue.java | 7 +- .../bcel/internal/classfile/EmptyVisitor.java | 9 + .../internal/classfile/ExceptionTable.java | 11 +- .../apache/bcel/internal/classfile/Field.java | 38 +- .../internal/classfile/FieldOrMethod.java | 38 +- .../bcel/internal/classfile/InnerClass.java | 2 +- .../bcel/internal/classfile/InnerClasses.java | 8 +- .../InvalidMethodSignatureException.java | 53 ++ .../bcel/internal/classfile/JavaClass.java | 152 +++- .../bcel/internal/classfile/LineNumber.java | 4 +- .../internal/classfile/LineNumberTable.java | 23 +- .../classfile/LocalVariableTable.java | 10 +- .../classfile/LocalVariableTypeTable.java | 11 +- .../bcel/internal/classfile/Method.java | 49 +- .../internal/classfile/MethodParameter.java | 12 +- .../internal/classfile/MethodParameters.java | 8 +- .../bcel/internal/classfile/Module.java | 66 +- .../internal/classfile/ModuleExports.java | 49 +- .../internal/classfile/ModuleMainClass.java | 2 +- .../bcel/internal/classfile/ModuleOpens.java | 49 +- .../internal/classfile/ModulePackages.java | 11 +- .../internal/classfile/ModuleProvides.java | 45 +- .../internal/classfile/ModuleRequires.java | 39 +- .../bcel/internal/classfile/NestMembers.java | 11 +- .../apache/bcel/internal/classfile/Node.java | 2 +- .../bcel/internal/classfile/PMGClass.java | 2 +- .../classfile/ParameterAnnotationEntry.java | 18 +- .../classfile/ParameterAnnotations.java | 8 +- .../bcel/internal/classfile/Record.java | 153 ++++ .../classfile/RecordComponentInfo.java | 139 +++ .../RuntimeInvisibleAnnotations.java | 8 +- .../RuntimeInvisibleParameterAnnotations.java | 2 + .../classfile/RuntimeVisibleAnnotations.java | 8 +- .../RuntimeVisibleParameterAnnotations.java | 2 + .../bcel/internal/classfile/Signature.java | 10 +- .../classfile/SimpleElementValue.java | 20 +- .../bcel/internal/classfile/SourceFile.java | 2 +- .../bcel/internal/classfile/StackMap.java | 10 +- .../internal/classfile/StackMapEntry.java | 13 +- .../bcel/internal/classfile/StackMapType.java | 29 +- .../bcel/internal/classfile/Synthetic.java | 2 +- .../bcel/internal/classfile/Utility.java | 60 +- .../bcel/internal/classfile/Visitor.java | 32 + .../bcel/internal/classfile/package-info.java | 25 + .../bcel/internal/generic/ARRAYLENGTH.java | 6 +- .../apache/bcel/internal/generic/ATHROW.java | 7 +- .../internal/generic/AnnotationEntryGen.java | 22 +- .../generic/ArrayElementValueGen.java | 15 +- .../bcel/internal/generic/ArrayType.java | 10 +- .../bcel/internal/generic/BranchHandle.java | 2 +- .../bcel/internal/generic/CPInstruction.java | 6 +- .../generic/ClassElementValueGen.java | 8 +- .../bcel/internal/generic/ClassGen.java | 82 +- .../internal/generic/CodeExceptionGen.java | 10 +- .../internal/generic/ElementValuePairGen.java | 4 +- .../internal/generic/EnumElementValueGen.java | 26 +- .../internal/generic/ExceptionThrower.java | 2 +- .../bcel/internal/generic/FieldGen.java | 42 +- .../internal/generic/FieldGenOrMethodGen.java | 12 +- .../bcel/internal/generic/FieldOrMethod.java | 4 +- .../apache/bcel/internal/generic/ICONST.java | 1 - .../bcel/internal/generic/INVOKEDYNAMIC.java | 8 +- .../bcel/internal/generic/Instruction.java | 6 +- .../internal/generic/InstructionConst.java | 2 +- .../internal/generic/InstructionFactory.java | 28 +- .../internal/generic/InstructionHandle.java | 15 +- .../internal/generic/InstructionList.java | 69 +- .../internal/generic/InstructionTargeter.java | 9 +- .../apache/bcel/internal/generic/LCMP.java | 1 - .../org/apache/bcel/internal/generic/LDC.java | 9 +- .../bcel/internal/generic/LineNumberGen.java | 4 +- .../internal/generic/LocalVariableGen.java | 2 +- .../generic/LocalVariableInstruction.java | 6 +- .../bcel/internal/generic/MethodGen.java | 53 +- .../bcel/internal/generic/ObjectType.java | 6 +- .../org/apache/bcel/internal/generic/RET.java | 2 +- .../bcel/internal/generic/ReferenceType.java | 62 +- .../apache/bcel/internal/generic/SWITCH.java | 2 +- .../apache/bcel/internal/generic/Select.java | 14 +- .../generic/SimpleElementValueGen.java | 6 +- .../internal/generic/TargetLostException.java | 28 +- .../apache/bcel/internal/generic/Type.java | 70 +- .../internal/generic/TypedInstruction.java | 2 +- .../bcel/internal/generic/package-info.java | 26 + .../apache/bcel/internal/package-info.java | 26 + .../bcel/internal/util/BCELComparator.java | 23 +- .../bcel/internal/util/BCELFactory.java | 8 +- .../apache/bcel/internal/util/BCELifier.java | 91 +- .../apache/bcel/internal/util/Class2HTML.java | 10 +- .../apache/bcel/internal/util/ClassSet.java | 4 +- .../apache/bcel/internal/util/CodeHTML.java | 2 +- .../bcel/internal/util/InstructionFinder.java | 7 +- .../apache/bcel/internal/util/Repository.java | 6 +- .../bcel/internal/util/package-info.java | 32 + .../share/classes/jdk/xml/internal/Utils.java | 60 +- src/java.xml/share/legal/bcel.md | 2 +- 122 files changed, 2461 insertions(+), 1128 deletions(-) create mode 100644 src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InvalidMethodSignatureException.java create mode 100644 src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Record.java create mode 100644 src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RecordComponentInfo.java create mode 100644 src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/package-info.java create mode 100644 src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/package-info.java create mode 100644 src/java.xml/share/classes/com/sun/org/apache/bcel/internal/package-info.java create mode 100644 src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/package-info.java diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/Const.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/Const.java index bca72ab3f95..c6b97db142e 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/Const.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/Const.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -26,12 +26,12 @@ import java.util.Collections; * Constants for the project, mostly defined in the JVM specification. * * @since 6.0 (intended to replace the Constants interface) - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public final class Const { /** - * Java class file format Magic number (0xCAFEBABE) + * Java class file format Magic number: {@value}. * * @see The ClassFile Structure * in The Java Virtual Machine Specification @@ -39,201 +39,201 @@ public final class Const { public static final int JVM_CLASSFILE_MAGIC = 0xCAFEBABE; /** - * Major version number of class files for Java 1.1. + * Major version number of class files for Java 1.1: {@value}. * * @see #MINOR_1_1 */ public static final short MAJOR_1_1 = 45; /** - * Minor version number of class files for Java 1.1. + * Minor version number of class files for Java 1.1: {@value}. * * @see #MAJOR_1_1 */ public static final short MINOR_1_1 = 3; /** - * Major version number of class files for Java 1.2. + * Major version number of class files for Java 1.2: {@value}. * * @see #MINOR_1_2 */ public static final short MAJOR_1_2 = 46; /** - * Minor version number of class files for Java 1.2. + * Minor version number of class files for Java 1.2: {@value}. * * @see #MAJOR_1_2 */ public static final short MINOR_1_2 = 0; /** - * Major version number of class files for Java 1.2. + * Major version number of class files for Java 1.2: {@value}. * * @see #MINOR_1_2 */ public static final short MAJOR_1_3 = 47; /** - * Minor version number of class files for Java 1.3. + * Minor version number of class files for Java 1.3: {@value}. * * @see #MAJOR_1_3 */ public static final short MINOR_1_3 = 0; /** - * Major version number of class files for Java 1.3. + * Major version number of class files for Java 1.3: {@value}. * * @see #MINOR_1_3 */ public static final short MAJOR_1_4 = 48; /** - * Minor version number of class files for Java 1.4. + * Minor version number of class files for Java 1.4: {@value}. * * @see #MAJOR_1_4 */ public static final short MINOR_1_4 = 0; /** - * Major version number of class files for Java 1.4. + * Major version number of class files for Java 1.4: {@value}. * * @see #MINOR_1_4 */ public static final short MAJOR_1_5 = 49; /** - * Minor version number of class files for Java 1.5. + * Minor version number of class files for Java 1.5: {@value}. * * @see #MAJOR_1_5 */ public static final short MINOR_1_5 = 0; /** - * Major version number of class files for Java 1.6. + * Major version number of class files for Java 1.6: {@value}. * * @see #MINOR_1_6 */ public static final short MAJOR_1_6 = 50; /** - * Minor version number of class files for Java 1.6. + * Minor version number of class files for Java 1.6: {@value}. * * @see #MAJOR_1_6 */ public static final short MINOR_1_6 = 0; /** - * Major version number of class files for Java 1.7. + * Major version number of class files for Java 1.7: {@value}. * * @see #MINOR_1_7 */ public static final short MAJOR_1_7 = 51; /** - * Minor version number of class files for Java 1.7. + * Minor version number of class files for Java 1.7: {@value}. * * @see #MAJOR_1_7 */ public static final short MINOR_1_7 = 0; /** - * Major version number of class files for Java 1.8. + * Major version number of class files for Java 1.8: {@value}. * * @see #MINOR_1_8 */ public static final short MAJOR_1_8 = 52; /** - * Minor version number of class files for Java 1.8. + * Minor version number of class files for Java 1.8: {@value}. * * @see #MAJOR_1_8 */ public static final short MINOR_1_8 = 0; /** - * Major version number of class files for Java 9. + * Major version number of class files for Java 9: {@value}. * * @see #MINOR_9 */ public static final short MAJOR_9 = 53; /** - * Minor version number of class files for Java 9. + * Minor version number of class files for Java 9: {@value}. * * @see #MAJOR_9 */ public static final short MINOR_9 = 0; /** - * @deprecated Use {@link #MAJOR_9} instead + * @deprecated Use {@link #MAJOR_9} ({@value}) instead. */ @Deprecated public static final short MAJOR_1_9 = MAJOR_9; /** - * @deprecated Use {@link #MINOR_9} instead + * @deprecated Use {@link #MINOR_9} ({@value}) instead. */ @Deprecated public static final short MINOR_1_9 = MINOR_9; /** - * Major version number of class files for Java 10. + * Major version number of class files for Java 10: {@value}. * * @see #MINOR_10 */ public static final short MAJOR_10 = 54; /** - * Minor version number of class files for Java 10. + * Minor version number of class files for Java 10: {@value}. * * @see #MAJOR_10 */ public static final short MINOR_10 = 0; /** - * Major version number of class files for Java 11. + * Major version number of class files for Java 11: {@value}. * * @see #MINOR_11 */ public static final short MAJOR_11 = 55; /** - * Minor version number of class files for Java 11. + * Minor version number of class files for Java 11: {@value}. * * @see #MAJOR_11 */ public static final short MINOR_11 = 0; /** - * Major version number of class files for Java 12. + * Major version number of class files for Java 12: {@value}. * * @see #MINOR_12 */ public static final short MAJOR_12 = 56; /** - * Minor version number of class files for Java 12. + * Minor version number of class files for Java 12: {@value}. * * @see #MAJOR_12 */ public static final short MINOR_12 = 0; /** - * Major version number of class files for Java 13. + * Major version number of class files for Java 13: {@value}. * * @see #MINOR_13 */ public static final short MAJOR_13 = 57; /** - * Minor version number of class files for Java 13. + * Minor version number of class files for Java 13: {@value}. * * @see #MAJOR_13 */ public static final short MINOR_13 = 0; /** - * Minor version number of class files for Java 14. + * Minor version number of class files for Java 14: {@value}. * * @see #MAJOR_14 * @since 6.4.0 @@ -241,7 +241,7 @@ public final class Const { public static final short MINOR_14 = 0; /** - * Minor version number of class files for Java 15. + * Minor version number of class files for Java 15: {@value}. * * @see #MAJOR_15 * @since 6.6.0 @@ -249,7 +249,7 @@ public final class Const { public static final short MINOR_15 = 0; /** - * Minor version number of class files for Java 16. + * Minor version number of class files for Java 16: {@value}. * * @see #MAJOR_16 * @since 6.6.0 @@ -257,7 +257,7 @@ public final class Const { public static final short MINOR_16 = 0; /** - * Minor version number of class files for Java 17. + * Minor version number of class files for Java 17: {@value}. * * @see #MAJOR_17 * @since 6.6.0 @@ -265,7 +265,7 @@ public final class Const { public static final short MINOR_17 = 0; /** - * Minor version number of class files for Java 18. + * Minor version number of class files for Java 18: {@value}. * * @see #MAJOR_18 * @since 6.6.0 @@ -273,7 +273,7 @@ public final class Const { public static final short MINOR_18 = 0; /** - * Minor version number of class files for Java 19. + * Minor version number of class files for Java 19: {@value}. * * @see #MAJOR_19 * @since 6.6.0 @@ -281,7 +281,47 @@ public final class Const { public static final short MINOR_19 = 0; /** - * Major version number of class files for Java 14. + * Minor version number of class files for Java 20: {@value}. + * + * @see #MAJOR_20 + * @since 6.8.0 + */ + public static final short MINOR_20 = 0; + + /** + * Minor version number of class files for Java 21: {@value}. + * + * @see #MAJOR_21 + * @since 6.8.0 + */ + public static final short MINOR_21 = 0; + + /** + * Minor version number of class files for Java 22: {@value}. + * + * @see #MAJOR_22 + * @since 6.10.0 + */ + public static final short MINOR_22 = 0; + + /** + * Minor version number of class files for Java 23: {@value}. + * + * @see #MAJOR_23 + * @since 6.10.0 + */ + public static final short MINOR_23 = 0; + + /** + * Minor version number of class files for Java 24: {@value}. + * + * @see #MAJOR_24 + * @since 6.10.0 + */ + public static final short MINOR_24 = 0; + + /** + * Major version number of class files for Java 14: {@value}. * * @see #MINOR_14 * @since 6.4.0 @@ -289,7 +329,7 @@ public final class Const { public static final short MAJOR_14 = 58; /** - * Major version number of class files for Java 15. + * Major version number of class files for Java 15: {@value}. * * @see #MINOR_15 * @since 6.6.0 @@ -297,7 +337,7 @@ public final class Const { public static final short MAJOR_15 = 59; /** - * Major version number of class files for Java 16. + * Major version number of class files for Java 16: {@value}. * * @see #MINOR_16 * @since 6.6.0 @@ -305,7 +345,7 @@ public final class Const { public static final short MAJOR_16 = 60; /** - * Major version number of class files for Java 17. + * Major version number of class files for Java 17: {@value}. * * @see #MINOR_17 * @since 6.6.0 @@ -313,7 +353,7 @@ public final class Const { public static final short MAJOR_17 = 61; /** - * Major version number of class files for Java 18. + * Major version number of class files for Java 18: {@value}. * * @see #MINOR_18 * @since 6.6.0 @@ -321,7 +361,7 @@ public final class Const { public static final short MAJOR_18 = 62; /** - * Major version number of class files for Java 19. + * Major version number of class files for Java 19: {@value}. * * @see #MINOR_19 * @since 6.6.0 @@ -329,31 +369,71 @@ public final class Const { public static final short MAJOR_19 = 63; /** - * Default major version number. Class file is for Java 1.1. + * Major version number of class files for Java 20: {@value}. + * + * @see #MINOR_20 + * @since 6.8.0 + */ + public static final short MAJOR_20 = 64; + + /** + * Major version number of class files for Java 21: {@value}. + * + * @see #MINOR_21 + * @since 6.8.0 + */ + public static final short MAJOR_21 = 65; + + /** + * Major version number of class files for Java 22: {@value}. + * + * @see #MINOR_22 + * @since 6.10.0 + */ + public static final short MAJOR_22 = 66; + + /** + * Major version number of class files for Java 23: {@value}. + * + * @see #MINOR_23 + * @since 6.10.0 + */ + public static final short MAJOR_23 = 67; + + /** + * Major version number of class files for Java 24: {@value}. + * + * @see #MINOR_24 + * @since 6.10.0 + */ + public static final short MAJOR_24 = 68; + + /** + * Default major version number. Class file is for Java 1.1: {@value}. * * @see #MAJOR_1_1 */ public static final short MAJOR = MAJOR_1_1; /** - * Default major version number. Class file is for Java 1.1. + * Default major version number. Class file is for Java 1.1: {@value}. * * @see #MAJOR_1_1 */ public static final short MINOR = MINOR_1_1; /** - * Maximum value for an unsigned short. + * Maximum value for an unsigned short: {@value}. */ public static final int MAX_SHORT = 65535; // 2^16 - 1 /** - * Maximum value for an unsigned byte. + * Maximum value for an unsigned byte: {@value}. */ public static final int MAX_BYTE = 255; // 2^8 - 1 /** - * One of the access flags for fields, methods, or classes. + * One of the access flags for fields, methods, or classes: {@value}. * * @see Flag definitions for * Classes in the Java Virtual Machine Specification (Java SE 9 Edition). @@ -367,140 +447,140 @@ public final class Const { public static final short ACC_PUBLIC = 0x0001; /** - * One of the access flags for fields, methods, or classes. + * One of the access flags for fields, methods, or classes: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_PRIVATE = 0x0002; /** - * One of the access flags for fields, methods, or classes. + * One of the access flags for fields, methods, or classes: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_PROTECTED = 0x0004; /** - * One of the access flags for fields, methods, or classes. + * One of the access flags for fields, methods, or classes: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_STATIC = 0x0008; /** - * One of the access flags for fields, methods, or classes. + * One of the access flags for fields, methods, or classes: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_FINAL = 0x0010; /** - * One of the access flags for the Module attribute. + * One of the access flags for the Module attribute: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_OPEN = 0x0020; /** - * One of the access flags for classes. + * One of the access flags for classes: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_SUPER = 0x0020; /** - * One of the access flags for methods. + * One of the access flags for methods: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_SYNCHRONIZED = 0x0020; /** - * One of the access flags for the Module attribute. + * One of the access flags for the Module attribute: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_TRANSITIVE = 0x0020; /** - * One of the access flags for methods. + * One of the access flags for methods: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_BRIDGE = 0x0040; /** - * One of the access flags for the Module attribute. + * One of the access flags for the Module attribute: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_STATIC_PHASE = 0x0040; /** - * One of the access flags for fields. + * One of the access flags for fields: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_VOLATILE = 0x0040; /** - * One of the access flags for fields. + * One of the access flags for fields: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_TRANSIENT = 0x0080; /** - * One of the access flags for methods. + * One of the access flags for methods: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_VARARGS = 0x0080; /** - * One of the access flags for methods. + * One of the access flags for methods: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_NATIVE = 0x0100; /** - * One of the access flags for classes. + * One of the access flags for classes: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_INTERFACE = 0x0200; /** - * One of the access flags for methods or classes. + * One of the access flags for methods or classes: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_ABSTRACT = 0x0400; /** - * One of the access flags for methods. + * One of the access flags for methods: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_STRICT = 0x0800; /** - * One of the access flags for fields, methods, classes, MethodParameter attribute, or Module attribute. + * One of the access flags for fields, methods, classes, MethodParameter attribute, or Module attribute: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_SYNTHETIC = 0x1000; /** - * One of the access flags for classes. + * One of the access flags for classes: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_ANNOTATION = 0x2000; /** - * One of the access flags for fields or classes. + * One of the access flags for fields or classes: {@value}. * * @see #ACC_PUBLIC */ @@ -508,21 +588,21 @@ public final class Const { // Applies to classes compiled by new compilers only /** - * One of the access flags for MethodParameter or Module attributes. + * One of the access flags for MethodParameter or Module attributes: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_MANDATED = (short) 0x8000; /** - * One of the access flags for classes. + * One of the access flags for classes: {@value}. * * @see #ACC_PUBLIC */ public static final short ACC_MODULE = (short) 0x8000; /** - * One of the access flags for fields, methods, or classes. + * One of the access flags for fields, methods, or classes: {@value}. * * @see #ACC_PUBLIC * @deprecated Use {@link #MAX_ACC_FLAG_I} @@ -531,7 +611,7 @@ public final class Const { public static final short MAX_ACC_FLAG = ACC_ENUM; /** - * One of the access flags for fields, methods, or classes. ACC_MODULE is negative as a short. + * One of the access flags for fields, methods, or classes. ACC_MODULE is negative as a short: {@value}. * * @see #ACC_PUBLIC * @since 6.4.0 @@ -553,7 +633,7 @@ public final class Const { public static final int ACCESS_NAMES_LENGTH = ACCESS_NAMES.length; /** - * Marks a constant pool entry as type UTF-8. + * Marks a constant pool entry as type UTF-8: {@value}. * * @see The Constant Pool in The * Java Virtual Machine Specification @@ -566,7 +646,7 @@ public final class Const { */ /** - * Marks a constant pool entry as type Integer. + * Marks a constant pool entry as type Integer: {@value}. * * @see The Constant Pool in The * Java Virtual Machine Specification @@ -574,7 +654,7 @@ public final class Const { public static final byte CONSTANT_Integer = 3; /** - * Marks a constant pool entry as type Float. + * Marks a constant pool entry as type Float: {@value}. * * @see The Constant Pool in The * Java Virtual Machine Specification @@ -582,7 +662,7 @@ public final class Const { public static final byte CONSTANT_Float = 4; /** - * Marks a constant pool entry as type Long. + * Marks a constant pool entry as type Long: {@value}. * * @see The Constant Pool in The * Java Virtual Machine Specification @@ -590,7 +670,7 @@ public final class Const { public static final byte CONSTANT_Long = 5; /** - * Marks a constant pool entry as type Double. + * Marks a constant pool entry as type Double: {@value}. * * @see The Constant Pool in The * Java Virtual Machine Specification @@ -598,7 +678,7 @@ public final class Const { public static final byte CONSTANT_Double = 6; /** - * Marks a constant pool entry as a Class + * Marks a constant pool entry as a Class: {@value}. * * @see The Constant Pool in The * Java Virtual Machine Specification @@ -606,7 +686,7 @@ public final class Const { public static final byte CONSTANT_Class = 7; /** - * Marks a constant pool entry as a Field Reference. + * Marks a constant pool entry as a Field Reference: {@value}. * * @see The Constant Pool in The * Java Virtual Machine Specification @@ -614,7 +694,7 @@ public final class Const { public static final byte CONSTANT_Fieldref = 9; /** - * Marks a constant pool entry as type String + * Marks a constant pool entry as type String: {@value}. * * @see The Constant Pool in The * Java Virtual Machine Specification @@ -622,7 +702,7 @@ public final class Const { public static final byte CONSTANT_String = 8; /** - * Marks a constant pool entry as a Method Reference. + * Marks a constant pool entry as a Method Reference: {@value}. * * @see The Constant Pool in The * Java Virtual Machine Specification @@ -630,7 +710,7 @@ public final class Const { public static final byte CONSTANT_Methodref = 10; /** - * Marks a constant pool entry as an Interface Method Reference. + * Marks a constant pool entry as an Interface Method Reference: {@value}. * * @see The Constant Pool in The * Java Virtual Machine Specification @@ -638,7 +718,7 @@ public final class Const { public static final byte CONSTANT_InterfaceMethodref = 11; /** - * Marks a constant pool entry as a name and type. + * Marks a constant pool entry as a name and type: {@value}. * * @see The Constant Pool in The * Java Virtual Machine Specification @@ -646,7 +726,7 @@ public final class Const { public static final byte CONSTANT_NameAndType = 12; /** - * Marks a constant pool entry as a Method Handle. + * Marks a constant pool entry as a Method Handle: {@value}. * * @see The Constant Pool in The * Java Virtual Machine Specification @@ -654,7 +734,7 @@ public final class Const { public static final byte CONSTANT_MethodHandle = 15; /** - * Marks a constant pool entry as a Method Type. + * Marks a constant pool entry as a Method Type: {@value}. * * @see The Constant Pool in The * Java Virtual Machine Specification @@ -662,16 +742,16 @@ public final class Const { public static final byte CONSTANT_MethodType = 16; /** - * Marks a constant pool entry as dynamically computed. + * Marks a constant pool entry as dynamically computed: {@value}. * - * @see Change request for JEP - * 309 + * @see The Constant Pool in The + * Java Virtual Machine Specification * @since 6.3 */ public static final byte CONSTANT_Dynamic = 17; /** - * Marks a constant pool entry as an Invoke Dynamic + * Marks a constant pool entry as an Invoke Dynamic: {@value}. * * @see The Constant Pool in The * Java Virtual Machine Specification @@ -679,7 +759,7 @@ public final class Const { public static final byte CONSTANT_InvokeDynamic = 18; /** - * Marks a constant pool entry as a Module Reference. + * Marks a constant pool entry as a Module Reference: {@value}. * * @see The Constant Pool in The * Java Virtual Machine Specification @@ -688,7 +768,7 @@ public final class Const { public static final byte CONSTANT_Module = 19; /** - * Marks a constant pool entry as a Package Reference. + * Marks a constant pool entry as a Package Reference: {@value}. * * @see The Constant Pool in The * Java Virtual Machine Specification @@ -705,23 +785,23 @@ public final class Const { /** * The name of the static initializer, also called "class initialization method" or "interface - * initialization method". This is "<clinit>". + * initialization method". This is {@value}. */ public static final String STATIC_INITIALIZER_NAME = ""; /** * The name of every constructor method in a class, also called "instance initialization method". This is - * "<init>". + * {@value}. */ public static final String CONSTRUCTOR_NAME = ""; /** - * The names of the interfaces implemented by arrays + * The names of the interfaces implemented by arrays. */ private static final String[] INTERFACES_IMPLEMENTED_BY_ARRAYS = {"java.lang.Cloneable", "java.io.Serializable"}; /** - * Maximum Constant Pool entries. One of the limitations of the Java Virtual Machine. + * Maximum Constant Pool entries: {@value}. One of the limitations of the Java Virtual Machine. * * @see The Java Virtual * Machine Specification, Java SE 8 Edition, page 330, chapter 4.11. @@ -729,21 +809,25 @@ public final class Const { public static final int MAX_CP_ENTRIES = 65535; /** - * Maximum code size (plus one; the code size must be LESS than this) One of the limitations of the Java Virtual - * Machine. Note vmspec2 page 152 ("Limitations") says: "The amount of code per non-native, non-abstract method is - * limited to 65536 bytes by the sizes of the indices in the exception_table of the Code attribute (4.7.3), in the - * LineNumberTable attribute (4.7.8), and in the LocalVariableTable attribute (4.7.9)." However this should be taken - * as an upper limit rather than the defined maximum. On page 134 (4.8.1 Static Constants) of the same spec, it says: - * "The value of the code_length item must be less than 65536." The entry in the Limitations section has been removed - * from later versions of the spec; it is not present in the Java SE 8 edition. + * Maximum code size (plus one; the code size must be LESS than this): {@value}. + *

+ * One of the limitations of the Java Virtual Machine. Note vmspec2 page 152 ("Limitations") says: + *

+ *
"The amount of code per non-native, non-abstract method is limited to 65536 bytes by the sizes of the indices in the exception_table of the Code
+     * attribute (4.7.3), in the LineNumberTable attribute (4.7.8), and in the LocalVariableTable attribute (4.7.9)." However this should be taken as an
+     * upper limit rather than the defined maximum. On page 134 (4.8.1 Static Constants) of the same spec, it says: "The value of the code_length item must be
+     * less than 65536."
+ *

+ * The entry in the Limitations section has been removed from later versions of the specification; it is not present in the Java SE 8 edition. + *

* - * @see The Java Virtual - * Machine Specification, Java SE 8 Edition, page 104, chapter 4.7. + * @see The Java Virtual Machine Specification, Java SE 8 + * Edition, page 104, chapter 4.7. */ public static final int MAX_CODE_SIZE = 65536; // bytes /** - * The maximum number of dimensions in an array ({@value}). One of the limitations of the Java Virtual Machine. + * The maximum number of dimensions in an array: {@value}. One of the limitations of the Java Virtual Machine. * * @see Field Descriptors in * The Java Virtual Machine Specification @@ -751,7 +835,7 @@ public final class Const { public static final int MAX_ARRAY_DIMENSIONS = 255; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -759,7 +843,7 @@ public final class Const { public static final short NOP = 0; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -767,7 +851,7 @@ public final class Const { public static final short ACONST_NULL = 1; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -775,7 +859,7 @@ public final class Const { public static final short ICONST_M1 = 2; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -783,7 +867,7 @@ public final class Const { public static final short ICONST_0 = 3; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -791,7 +875,7 @@ public final class Const { public static final short ICONST_1 = 4; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -799,7 +883,7 @@ public final class Const { public static final short ICONST_2 = 5; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -807,7 +891,7 @@ public final class Const { public static final short ICONST_3 = 6; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -815,7 +899,7 @@ public final class Const { public static final short ICONST_4 = 7; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -823,7 +907,7 @@ public final class Const { public static final short ICONST_5 = 8; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -831,7 +915,7 @@ public final class Const { public static final short LCONST_0 = 9; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -839,7 +923,7 @@ public final class Const { public static final short LCONST_1 = 10; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -847,7 +931,7 @@ public final class Const { public static final short FCONST_0 = 11; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -855,7 +939,7 @@ public final class Const { public static final short FCONST_1 = 12; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -863,7 +947,7 @@ public final class Const { public static final short FCONST_2 = 13; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -871,7 +955,7 @@ public final class Const { public static final short DCONST_0 = 14; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -879,7 +963,7 @@ public final class Const { public static final short DCONST_1 = 15; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -887,7 +971,7 @@ public final class Const { public static final short BIPUSH = 16; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -895,7 +979,7 @@ public final class Const { public static final short SIPUSH = 17; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -903,7 +987,7 @@ public final class Const { public static final short LDC = 18; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -911,7 +995,7 @@ public final class Const { public static final short LDC_W = 19; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -919,7 +1003,7 @@ public final class Const { public static final short LDC2_W = 20; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -927,7 +1011,7 @@ public final class Const { public static final short ILOAD = 21; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -935,7 +1019,7 @@ public final class Const { public static final short LLOAD = 22; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -943,7 +1027,7 @@ public final class Const { public static final short FLOAD = 23; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -951,7 +1035,7 @@ public final class Const { public static final short DLOAD = 24; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -959,7 +1043,7 @@ public final class Const { public static final short ALOAD = 25; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -967,7 +1051,7 @@ public final class Const { public static final short ILOAD_0 = 26; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -975,7 +1059,7 @@ public final class Const { public static final short ILOAD_1 = 27; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -983,7 +1067,7 @@ public final class Const { public static final short ILOAD_2 = 28; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -991,7 +1075,7 @@ public final class Const { public static final short ILOAD_3 = 29; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -999,7 +1083,7 @@ public final class Const { public static final short LLOAD_0 = 30; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1007,7 +1091,7 @@ public final class Const { public static final short LLOAD_1 = 31; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1015,7 +1099,7 @@ public final class Const { public static final short LLOAD_2 = 32; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1023,7 +1107,7 @@ public final class Const { public static final short LLOAD_3 = 33; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1031,7 +1115,7 @@ public final class Const { public static final short FLOAD_0 = 34; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1039,7 +1123,7 @@ public final class Const { public static final short FLOAD_1 = 35; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1047,7 +1131,7 @@ public final class Const { public static final short FLOAD_2 = 36; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1055,7 +1139,7 @@ public final class Const { public static final short FLOAD_3 = 37; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1063,7 +1147,7 @@ public final class Const { public static final short DLOAD_0 = 38; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1071,7 +1155,7 @@ public final class Const { public static final short DLOAD_1 = 39; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1079,7 +1163,7 @@ public final class Const { public static final short DLOAD_2 = 40; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1087,7 +1171,7 @@ public final class Const { public static final short DLOAD_3 = 41; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1095,7 +1179,7 @@ public final class Const { public static final short ALOAD_0 = 42; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1103,7 +1187,7 @@ public final class Const { public static final short ALOAD_1 = 43; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1111,7 +1195,7 @@ public final class Const { public static final short ALOAD_2 = 44; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1119,7 +1203,7 @@ public final class Const { public static final short ALOAD_3 = 45; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1127,7 +1211,7 @@ public final class Const { public static final short IALOAD = 46; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1135,7 +1219,7 @@ public final class Const { public static final short LALOAD = 47; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1143,7 +1227,7 @@ public final class Const { public static final short FALOAD = 48; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1151,7 +1235,7 @@ public final class Const { public static final short DALOAD = 49; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1159,7 +1243,7 @@ public final class Const { public static final short AALOAD = 50; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1167,7 +1251,7 @@ public final class Const { public static final short BALOAD = 51; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1175,7 +1259,7 @@ public final class Const { public static final short CALOAD = 52; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1183,7 +1267,7 @@ public final class Const { public static final short SALOAD = 53; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1191,7 +1275,7 @@ public final class Const { public static final short ISTORE = 54; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1199,7 +1283,7 @@ public final class Const { public static final short LSTORE = 55; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1207,7 +1291,7 @@ public final class Const { public static final short FSTORE = 56; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1215,7 +1299,7 @@ public final class Const { public static final short DSTORE = 57; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1223,7 +1307,7 @@ public final class Const { public static final short ASTORE = 58; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1231,7 +1315,7 @@ public final class Const { public static final short ISTORE_0 = 59; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1239,7 +1323,7 @@ public final class Const { public static final short ISTORE_1 = 60; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1247,7 +1331,7 @@ public final class Const { public static final short ISTORE_2 = 61; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1255,7 +1339,7 @@ public final class Const { public static final short ISTORE_3 = 62; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1263,7 +1347,7 @@ public final class Const { public static final short LSTORE_0 = 63; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1271,7 +1355,7 @@ public final class Const { public static final short LSTORE_1 = 64; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1279,7 +1363,7 @@ public final class Const { public static final short LSTORE_2 = 65; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1287,7 +1371,7 @@ public final class Const { public static final short LSTORE_3 = 66; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1295,7 +1379,7 @@ public final class Const { public static final short FSTORE_0 = 67; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1303,7 +1387,7 @@ public final class Const { public static final short FSTORE_1 = 68; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1311,7 +1395,7 @@ public final class Const { public static final short FSTORE_2 = 69; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1319,7 +1403,7 @@ public final class Const { public static final short FSTORE_3 = 70; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1327,7 +1411,7 @@ public final class Const { public static final short DSTORE_0 = 71; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1335,7 +1419,7 @@ public final class Const { public static final short DSTORE_1 = 72; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1343,7 +1427,7 @@ public final class Const { public static final short DSTORE_2 = 73; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1351,7 +1435,7 @@ public final class Const { public static final short DSTORE_3 = 74; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1359,7 +1443,7 @@ public final class Const { public static final short ASTORE_0 = 75; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1367,7 +1451,7 @@ public final class Const { public static final short ASTORE_1 = 76; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1375,7 +1459,7 @@ public final class Const { public static final short ASTORE_2 = 77; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -1383,7 +1467,7 @@ public final class Const { public static final short ASTORE_3 = 78; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1391,7 +1475,7 @@ public final class Const { public static final short IASTORE = 79; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1399,7 +1483,7 @@ public final class Const { public static final short LASTORE = 80; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1407,7 +1491,7 @@ public final class Const { public static final short FASTORE = 81; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1415,7 +1499,7 @@ public final class Const { public static final short DASTORE = 82; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1423,7 +1507,7 @@ public final class Const { public static final short AASTORE = 83; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1431,7 +1515,7 @@ public final class Const { public static final short BASTORE = 84; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1439,7 +1523,7 @@ public final class Const { public static final short CASTORE = 85; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1447,7 +1531,7 @@ public final class Const { public static final short SASTORE = 86; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1455,7 +1539,7 @@ public final class Const { public static final short POP = 87; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1463,7 +1547,7 @@ public final class Const { public static final short POP2 = 88; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1471,7 +1555,7 @@ public final class Const { public static final short DUP = 89; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1479,7 +1563,7 @@ public final class Const { public static final short DUP_X1 = 90; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1487,7 +1571,7 @@ public final class Const { public static final short DUP_X2 = 91; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1495,7 +1579,7 @@ public final class Const { public static final short DUP2 = 92; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1503,7 +1587,7 @@ public final class Const { public static final short DUP2_X1 = 93; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1511,7 +1595,7 @@ public final class Const { public static final short DUP2_X2 = 94; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1519,7 +1603,7 @@ public final class Const { public static final short SWAP = 95; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1527,7 +1611,7 @@ public final class Const { public static final short IADD = 96; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1535,7 +1619,7 @@ public final class Const { public static final short LADD = 97; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1543,7 +1627,7 @@ public final class Const { public static final short FADD = 98; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1551,7 +1635,7 @@ public final class Const { public static final short DADD = 99; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1559,7 +1643,7 @@ public final class Const { public static final short ISUB = 100; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1567,7 +1651,7 @@ public final class Const { public static final short LSUB = 101; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1575,7 +1659,7 @@ public final class Const { public static final short FSUB = 102; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1583,7 +1667,7 @@ public final class Const { public static final short DSUB = 103; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1591,7 +1675,7 @@ public final class Const { public static final short IMUL = 104; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1599,7 +1683,7 @@ public final class Const { public static final short LMUL = 105; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1607,7 +1691,7 @@ public final class Const { public static final short FMUL = 106; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1615,7 +1699,7 @@ public final class Const { public static final short DMUL = 107; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1623,7 +1707,7 @@ public final class Const { public static final short IDIV = 108; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1631,7 +1715,7 @@ public final class Const { public static final short LDIV = 109; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1639,7 +1723,7 @@ public final class Const { public static final short FDIV = 110; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1647,7 +1731,7 @@ public final class Const { public static final short DDIV = 111; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1655,7 +1739,7 @@ public final class Const { public static final short IREM = 112; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1663,7 +1747,7 @@ public final class Const { public static final short LREM = 113; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1671,7 +1755,7 @@ public final class Const { public static final short FREM = 114; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1679,7 +1763,7 @@ public final class Const { public static final short DREM = 115; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1687,7 +1771,7 @@ public final class Const { public static final short INEG = 116; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1695,7 +1779,7 @@ public final class Const { public static final short LNEG = 117; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1703,7 +1787,7 @@ public final class Const { public static final short FNEG = 118; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1711,7 +1795,7 @@ public final class Const { public static final short DNEG = 119; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1719,7 +1803,7 @@ public final class Const { public static final short ISHL = 120; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1727,7 +1811,7 @@ public final class Const { public static final short LSHL = 121; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1735,7 +1819,7 @@ public final class Const { public static final short ISHR = 122; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1743,7 +1827,7 @@ public final class Const { public static final short LSHR = 123; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1751,7 +1835,7 @@ public final class Const { public static final short IUSHR = 124; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1759,7 +1843,7 @@ public final class Const { public static final short LUSHR = 125; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1767,7 +1851,7 @@ public final class Const { public static final short IAND = 126; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1775,7 +1859,7 @@ public final class Const { public static final short LAND = 127; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1783,7 +1867,7 @@ public final class Const { public static final short IOR = 128; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1791,7 +1875,7 @@ public final class Const { public static final short LOR = 129; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1799,7 +1883,7 @@ public final class Const { public static final short IXOR = 130; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1807,7 +1891,7 @@ public final class Const { public static final short LXOR = 131; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1815,7 +1899,7 @@ public final class Const { public static final short IINC = 132; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1823,7 +1907,7 @@ public final class Const { public static final short I2L = 133; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1831,7 +1915,7 @@ public final class Const { public static final short I2F = 134; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1839,7 +1923,7 @@ public final class Const { public static final short I2D = 135; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1847,7 +1931,7 @@ public final class Const { public static final short L2I = 136; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1855,7 +1939,7 @@ public final class Const { public static final short L2F = 137; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1863,7 +1947,7 @@ public final class Const { public static final short L2D = 138; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1871,7 +1955,7 @@ public final class Const { public static final short F2I = 139; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1879,7 +1963,7 @@ public final class Const { public static final short F2L = 140; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1887,7 +1971,7 @@ public final class Const { public static final short F2D = 141; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1895,7 +1979,7 @@ public final class Const { public static final short D2I = 142; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1903,7 +1987,7 @@ public final class Const { public static final short D2L = 143; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1911,7 +1995,7 @@ public final class Const { public static final short D2F = 144; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1919,7 +2003,7 @@ public final class Const { public static final short I2B = 145; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1927,7 +2011,7 @@ public final class Const { public static final short INT2BYTE = 145; // Old notation /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1935,7 +2019,7 @@ public final class Const { public static final short I2C = 146; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1943,7 +2027,7 @@ public final class Const { public static final short INT2CHAR = 146; // Old notation /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1951,7 +2035,7 @@ public final class Const { public static final short I2S = 147; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -1959,7 +2043,7 @@ public final class Const { public static final short INT2SHORT = 147; // Old notation /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1967,7 +2051,7 @@ public final class Const { public static final short LCMP = 148; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1975,7 +2059,7 @@ public final class Const { public static final short FCMPL = 149; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1983,7 +2067,7 @@ public final class Const { public static final short FCMPG = 150; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1991,7 +2075,7 @@ public final class Const { public static final short DCMPL = 151; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -1999,7 +2083,7 @@ public final class Const { public static final short DCMPG = 152; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -2007,7 +2091,7 @@ public final class Const { public static final short IFEQ = 153; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -2015,7 +2099,7 @@ public final class Const { public static final short IFNE = 154; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -2023,7 +2107,7 @@ public final class Const { public static final short IFLT = 155; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -2031,7 +2115,7 @@ public final class Const { public static final short IFGE = 156; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -2039,7 +2123,7 @@ public final class Const { public static final short IFGT = 157; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -2047,7 +2131,7 @@ public final class Const { public static final short IFLE = 158; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2055,7 +2139,7 @@ public final class Const { public static final short IF_ICMPEQ = 159; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2063,7 +2147,7 @@ public final class Const { public static final short IF_ICMPNE = 160; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2071,7 +2155,7 @@ public final class Const { public static final short IF_ICMPLT = 161; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2079,7 +2163,7 @@ public final class Const { public static final short IF_ICMPGE = 162; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2087,7 +2171,7 @@ public final class Const { public static final short IF_ICMPGT = 163; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2095,7 +2179,7 @@ public final class Const { public static final short IF_ICMPLE = 164; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2103,7 +2187,7 @@ public final class Const { public static final short IF_ACMPEQ = 165; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2111,7 +2195,7 @@ public final class Const { public static final short IF_ACMPNE = 166; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -2119,7 +2203,7 @@ public final class Const { public static final short GOTO = 167; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -2127,7 +2211,7 @@ public final class Const { public static final short JSR = 168; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -2135,7 +2219,7 @@ public final class Const { public static final short RET = 169; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2143,7 +2227,7 @@ public final class Const { public static final short TABLESWITCH = 170; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2151,7 +2235,7 @@ public final class Const { public static final short LOOKUPSWITCH = 171; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -2159,7 +2243,7 @@ public final class Const { public static final short IRETURN = 172; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -2167,7 +2251,7 @@ public final class Const { public static final short LRETURN = 173; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -2175,7 +2259,7 @@ public final class Const { public static final short FRETURN = 174; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -2183,7 +2267,7 @@ public final class Const { public static final short DRETURN = 175; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -2191,7 +2275,7 @@ public final class Const { public static final short ARETURN = 176; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -2199,7 +2283,7 @@ public final class Const { public static final short RETURN = 177; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -2207,7 +2291,7 @@ public final class Const { public static final short GETSTATIC = 178; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -2215,7 +2299,7 @@ public final class Const { public static final short PUTSTATIC = 179; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -2223,7 +2307,7 @@ public final class Const { public static final short GETFIELD = 180; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -2231,7 +2315,7 @@ public final class Const { public static final short PUTFIELD = 181; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2239,7 +2323,7 @@ public final class Const { public static final short INVOKEVIRTUAL = 182; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2247,7 +2331,7 @@ public final class Const { public static final short INVOKESPECIAL = 183; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -2255,7 +2339,7 @@ public final class Const { public static final short INVOKENONVIRTUAL = 183; // Old name in JDK 1.0 /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2263,7 +2347,7 @@ public final class Const { public static final short INVOKESTATIC = 184; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2271,7 +2355,7 @@ public final class Const { public static final short INVOKEINTERFACE = 185; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2279,7 +2363,7 @@ public final class Const { public static final short INVOKEDYNAMIC = 186; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in The * Java Virtual Machine Specification @@ -2287,7 +2371,7 @@ public final class Const { public static final short NEW = 187; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -2295,7 +2379,7 @@ public final class Const { public static final short NEWARRAY = 188; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -2303,7 +2387,7 @@ public final class Const { public static final short ANEWARRAY = 189; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2311,7 +2395,7 @@ public final class Const { public static final short ARRAYLENGTH = 190; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -2319,7 +2403,7 @@ public final class Const { public static final short ATHROW = 191; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -2327,7 +2411,7 @@ public final class Const { public static final short CHECKCAST = 192; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -2335,7 +2419,7 @@ public final class Const { public static final short INSTANCEOF = 193; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2343,7 +2427,7 @@ public final class Const { public static final short MONITORENTER = 194; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2351,7 +2435,7 @@ public final class Const { public static final short MONITOREXIT = 195; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -2359,7 +2443,7 @@ public final class Const { public static final short WIDE = 196; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode * definitions in The Java Virtual Machine Specification @@ -2367,7 +2451,7 @@ public final class Const { public static final short MULTIANEWARRAY = 197; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -2375,7 +2459,7 @@ public final class Const { public static final short IFNULL = 198; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions * in The Java Virtual Machine Specification @@ -2383,7 +2467,7 @@ public final class Const { public static final short IFNONNULL = 199; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -2391,7 +2475,7 @@ public final class Const { public static final short GOTO_W = 200; /** - * Java VM opcode. + * Java VM opcode {@value}. * * @see Opcode definitions in * The Java Virtual Machine Specification @@ -2399,7 +2483,7 @@ public final class Const { public static final short JSR_W = 201; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see Reserved opcodes in the Java * Virtual Machine Specification @@ -2407,7 +2491,7 @@ public final class Const { public static final short BREAKPOINT = 202; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2418,7 +2502,7 @@ public final class Const { public static final short LDC_QUICK = 203; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2429,7 +2513,7 @@ public final class Const { public static final short LDC_W_QUICK = 204; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2440,7 +2524,7 @@ public final class Const { public static final short LDC2_W_QUICK = 205; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2451,7 +2535,7 @@ public final class Const { public static final short GETFIELD_QUICK = 206; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2462,7 +2546,7 @@ public final class Const { public static final short PUTFIELD_QUICK = 207; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2473,7 +2557,7 @@ public final class Const { public static final short GETFIELD2_QUICK = 208; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2484,7 +2568,7 @@ public final class Const { public static final short PUTFIELD2_QUICK = 209; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2495,7 +2579,7 @@ public final class Const { public static final short GETSTATIC_QUICK = 210; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2506,7 +2590,7 @@ public final class Const { public static final short PUTSTATIC_QUICK = 211; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2517,7 +2601,7 @@ public final class Const { public static final short GETSTATIC2_QUICK = 212; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2528,7 +2612,7 @@ public final class Const { public static final short PUTSTATIC2_QUICK = 213; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2539,7 +2623,7 @@ public final class Const { public static final short INVOKEVIRTUAL_QUICK = 214; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2550,7 +2634,7 @@ public final class Const { public static final short INVOKENONVIRTUAL_QUICK = 215; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2561,7 +2645,7 @@ public final class Const { public static final short INVOKESUPER_QUICK = 216; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2572,7 +2656,7 @@ public final class Const { public static final short INVOKESTATIC_QUICK = 217; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2583,7 +2667,7 @@ public final class Const { public static final short INVOKEINTERFACE_QUICK = 218; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2594,7 +2678,7 @@ public final class Const { public static final short INVOKEVIRTUALOBJECT_QUICK = 219; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2605,7 +2689,7 @@ public final class Const { public static final short NEW_QUICK = 221; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2616,7 +2700,7 @@ public final class Const { public static final short ANEWARRAY_QUICK = 222; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2627,7 +2711,7 @@ public final class Const { public static final short MULTIANEWARRAY_QUICK = 223; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2638,7 +2722,7 @@ public final class Const { public static final short CHECKCAST_QUICK = 224; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2649,7 +2733,7 @@ public final class Const { public static final short INSTANCEOF_QUICK = 225; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2660,7 +2744,7 @@ public final class Const { public static final short INVOKEVIRTUAL_QUICK_W = 226; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2671,7 +2755,7 @@ public final class Const { public static final short GETFIELD_QUICK_W = 227; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see @@ -2682,7 +2766,7 @@ public final class Const { public static final short PUTFIELD_QUICK_W = 228; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see Reserved opcodes in the Java * Virtual Machine Specification @@ -2690,7 +2774,7 @@ public final class Const { public static final short IMPDEP1 = 254; /** - * JVM internal opcode. + * JVM internal opcode {@value}. * * @see Reserved opcodes in the Java * Virtual Machine Specification @@ -2698,34 +2782,44 @@ public final class Const { public static final short IMPDEP2 = 255; /** - * BCEL virtual instruction for pushing an arbitrary data type onto the stack. Will be converted to the appropriate JVM + * BCEL virtual instruction for pushing an arbitrary data type onto the stack: {@value}. Will be converted to the appropriate JVM * opcode when the class is dumped. */ public static final short PUSH = 4711; /** - * BCEL virtual instruction for either LOOKUPSWITCH or TABLESWITCH. Will be converted to the appropriate JVM opcode when + * BCEL virtual instruction for either LOOKUPSWITCH or TABLESWITCH: {@value}. Will be converted to the appropriate JVM opcode when * the class is dumped. */ public static final short SWITCH = 4712; - /** Illegal opcode. */ + /** + * Illegal opcode: {@value}. + */ public static final short UNDEFINED = -1; - /** Illegal opcode. */ + /** + * Illegal opcode: {@value}. + */ public static final short UNPREDICTABLE = -2; - /** Illegal opcode. */ + /** + * Illegal opcode: {@value}. + */ public static final short RESERVED = -3; - /** Mnemonic for an illegal opcode. */ + /** + * Mnemonic for an illegal opcode: {@value}. + */ public static final String ILLEGAL_OPCODE = ""; - /** Mnemonic for an illegal type. */ + /** + * Mnemonic for an illegal type: {@value}. + */ public static final String ILLEGAL_TYPE = ""; /** - * Boolean data type. + * Boolean data type: {@value}. * * @see Static Constraints in * the Java Virtual Machine Specification @@ -2733,7 +2827,7 @@ public final class Const { public static final byte T_BOOLEAN = 4; /** - * Char data type. + * Char data type: {@value}. * * @see Static Constraints in * the Java Virtual Machine Specification @@ -2741,7 +2835,7 @@ public final class Const { public static final byte T_CHAR = 5; /** - * Float data type. + * Float data type: {@value}. * * @see Static Constraints in * the Java Virtual Machine Specification @@ -2749,7 +2843,7 @@ public final class Const { public static final byte T_FLOAT = 6; /** - * Double data type. + * Double data type: {@value}. * * @see Static Constraints in * the Java Virtual Machine Specification @@ -2757,7 +2851,7 @@ public final class Const { public static final byte T_DOUBLE = 7; /** - * Byte data type. + * Byte data type: {@value}. * * @see Static Constraints in * the Java Virtual Machine Specification @@ -2765,7 +2859,7 @@ public final class Const { public static final byte T_BYTE = 8; /** - * Short data type. + * Short data type: {@value}. * * @see Static Constraints in * the Java Virtual Machine Specification @@ -2773,7 +2867,7 @@ public final class Const { public static final byte T_SHORT = 9; /** - * Int data type. + * Int data type: {@value}. * * @see Static Constraints in * the Java Virtual Machine Specification @@ -2781,7 +2875,7 @@ public final class Const { public static final byte T_INT = 10; /** - * Long data type. + * Long data type: {@value}. * * @see Static Constraints in * the Java Virtual Machine Specification @@ -2827,7 +2921,7 @@ public final class Const { /** * The signature characters corresponding to primitive types, e.g., SHORT_TYPE_NAMES[T_INT] = "I" */ - private static final String[] SHORT_TYPE_NAMES = {ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE, "Z", "C", "F", "D", "B", "S", "I", "J", "V", + public static final String[] SHORT_TYPE_NAMES = {ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE, "Z", "C", "F", "D", "B", "S", "I", "J", "V", ILLEGAL_TYPE, ILLEGAL_TYPE, ILLEGAL_TYPE}; /** @@ -3036,11 +3130,13 @@ public final class Const { public static final byte ATTR_MODULE_MAIN_CLASS = 24; public static final byte ATTR_NEST_HOST = 25; public static final byte ATTR_NEST_MEMBERS = 26; - public static final short KNOWN_ATTRIBUTES = 27; // count of attributes + public static final byte ATTR_RECORD = 27; + + public static final short KNOWN_ATTRIBUTES = 28; // count of attributes private static final String[] ATTRIBUTE_NAMES = {"SourceFile", "ConstantValue", "Code", "Exceptions", "LineNumberTable", "LocalVariableTable", "InnerClasses", "Synthetic", "Deprecated", "PMGClass", "Signature", "StackMap", "RuntimeVisibleAnnotations", "RuntimeInvisibleAnnotations", "RuntimeVisibleParameterAnnotations", "RuntimeInvisibleParameterAnnotations", "AnnotationDefault", "LocalVariableTypeTable", "EnclosingMethod", - "StackMapTable", "BootstrapMethods", "MethodParameters", "Module", "ModulePackages", "ModuleMainClass", "NestHost", "NestMembers"}; + "StackMapTable", "BootstrapMethods", "MethodParameters", "Module", "ModulePackages", "ModuleMainClass", "NestHost", "NestMembers", "Record"}; /** * Constants used in the StackMap attribute. */ @@ -3070,6 +3166,7 @@ public final class Const { public static final int SAME_FRAME_EXTENDED = 251; public static final int APPEND_FRAME = 252; public static final int FULL_FRAME = 255; + /** * Constants that define the maximum value of those constants which store ranges. */ @@ -3090,6 +3187,7 @@ public final class Const { public static final byte REF_invokeSpecial = 7; public static final byte REF_newInvokeSpecial = 8; public static final byte REF_invokeInterface = 9; + /** * The names of the reference_kinds of a CONSTANT_MethodHandle_info. */ @@ -3097,7 +3195,7 @@ public final class Const { "newInvokeSpecial", "invokeInterface"}; /** - * @param index + * @param index index into {@code ACCESS_NAMES}. * @return the ACCESS_NAMES entry at the given index * @since 6.0 */ @@ -3107,7 +3205,7 @@ public final class Const { /** * - * @param index + * @param index index into {@code ACCESS_NAMES}. * @return the attribute name * @since 6.0 */ @@ -3118,7 +3216,7 @@ public final class Const { /** * The primitive class names corresponding to the T_XX constants, e.g., CLASS_TYPE_NAMES[T_INT] = "java.lang.Integer" * - * @param index + * @param index index into {@code CLASS_TYPE_NAMES}. * @return the class name * @since 6.0 */ @@ -3128,7 +3226,7 @@ public final class Const { /** * - * @param index + * @param index index into {@code CONSTANT_NAMES}. * @return the CONSTANT_NAMES entry at the given index * @since 6.0 */ @@ -3140,7 +3238,7 @@ public final class Const { /** * - * @param index + * @param index index into {@code CONSUME_STACK}. * @return Number of words consumed on operand stack * @since 6.0 */ @@ -3157,7 +3255,7 @@ public final class Const { /** * - * @param index + * @param index index into {@code ITEM_NAMES}. * @return the item name * @since 6.0 */ @@ -3167,7 +3265,7 @@ public final class Const { /** * - * @param index + * @param index index into {@code METHODHANDLE_NAMES}. * @return the method handle name * @since 6.0 */ @@ -3177,7 +3275,7 @@ public final class Const { /** * - * @param index + * @param index index into {@code NO_OF_OPERANDS}. * @return Number of byte code operands * @since 6.0 */ diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/ExceptionConst.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/ExceptionConst.java index d45c5794b7b..89cf3f835da 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/ExceptionConst.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/ExceptionConst.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -26,7 +26,7 @@ import jdk.xml.internal.Utils; * Exception constants. * * @since 6.0 (intended to replace the InstructionConstant interface) - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public final class ExceptionConst { @@ -52,7 +52,6 @@ public final class ExceptionConst { * Super class of any linking exception (aka Linkage Error) */ public static final Class LINKING_EXCEPTION = LinkageError.class; - /** * Linking Exceptions */ @@ -67,10 +66,10 @@ public final class ExceptionConst { public static final Class NO_SUCH_METHOD_ERROR = NoSuchMethodError.class; public static final Class NO_CLASS_DEF_FOUND_ERROR = NoClassDefFoundError.class; public static final Class UNSATISFIED_LINK_ERROR = UnsatisfiedLinkError.class; + public static final Class VERIFY_ERROR = VerifyError.class; /* UnsupportedClassVersionError is new in JDK 1.2 */ // public static final Class UnsupportedClassVersionError = UnsupportedClassVersionError.class; - /** * Run-Time Exceptions */ diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/Repository.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/Repository.java index d36260cc23a..10f6a1a8ff4 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/Repository.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/Repository.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -30,7 +30,7 @@ import com.sun.org.apache.bcel.internal.util.SyntheticRepository; * @see com.sun.org.apache.bcel.internal.util.Repository * @see SyntheticRepository * - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public abstract class Repository { @@ -174,7 +174,7 @@ public abstract class Repository { } /** - * Lookups class somewhere found on your CLASSPATH, or wherever the repository instance looks for it. + * Lookups class somewhere found on your CLASSPATH, or whereever the repository instance looks for it. * * @return class object for given fully qualified class name * @throws ClassNotFoundException if the class could not be found or parsed correctly diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/AccessFlags.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/AccessFlags.java index 61ec9c4d690..f1d350894c9 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/AccessFlags.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/AccessFlags.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -25,27 +25,36 @@ import com.sun.org.apache.bcel.internal.Const; * Super class for all objects that have modifiers like private, final, ... I.e. * classes, fields, and methods. * - * @LastModified: Jan 2020 + * @LastModified: Sept 2025 */ public abstract class AccessFlags { /** - * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter + * Access flags. + * + * @deprecated (since 6.0) will be made private; do not access directly, use getter/setter. */ @java.lang.Deprecated protected int access_flags; // TODO not used externally at present + /** + * Constructs a new instance. + */ public AccessFlags() { } /** - * @param a initial access flags + * Constructs a new instance. + * + * @param accessFlags initial access flags. */ - public AccessFlags(final int a) { - access_flags = a; + public AccessFlags(final int accessFlags) { + access_flags = accessFlags; } /** + * Gets access flags. + * * @return Access flags of the object aka. "modifiers". */ public final int getAccessFlags() { @@ -53,142 +62,303 @@ public abstract class AccessFlags { } /** - * @return Access flags of the object aka. "modifiers". + * Gets access flags. + * + * @return Access flags of the object also known as modifiers. */ public final int getModifiers() { return access_flags; } + /** + * Tests whether the abstract bit is on. + * + * @return whether the abstract bit is on. + */ public final boolean isAbstract() { - return (access_flags & Const.ACC_ABSTRACT) != 0; + return test(Const.ACC_ABSTRACT); } + /** + * Sets the abstract bit. + * + * @param flag The new value. + */ public final void isAbstract(final boolean flag) { setFlag(Const.ACC_ABSTRACT, flag); } + /** + * Tests whether the annotation bit is on. + * + * @return whether the annotation bit is on. + */ public final boolean isAnnotation() { - return (access_flags & Const.ACC_ANNOTATION) != 0; + return test(Const.ACC_ANNOTATION); } + /** + * Sets the annotation bit. + * + * @param flag The new value. + */ public final void isAnnotation(final boolean flag) { setFlag(Const.ACC_ANNOTATION, flag); } - + /** + * Tests whether the enum bit is on. + * + * @return whether the enum bit is on. + */ public final boolean isEnum() { - return (access_flags & Const.ACC_ENUM) != 0; + return test(Const.ACC_ENUM); } + /** + * Sets the enum bit. + * + * @param flag The new value. + */ public final void isEnum(final boolean flag) { setFlag(Const.ACC_ENUM, flag); } + /** + * Tests whether the final bit is on. + * + * @return whether the final bit is on. + */ public final boolean isFinal() { - return (access_flags & Const.ACC_FINAL) != 0; + return test(Const.ACC_FINAL); } + /** + * Sets the final bit. + * + * @param flag The new value. + */ public final void isFinal(final boolean flag) { setFlag(Const.ACC_FINAL, flag); } + /** + * Tests whether the interface bit is on. + * + * @return whether the interface bit is on. + */ public final boolean isInterface() { - return (access_flags & Const.ACC_INTERFACE) != 0; + return test(Const.ACC_INTERFACE); } + /** + * Sets the interface bit. + * + * @param flag The new value. + */ public final void isInterface(final boolean flag) { setFlag(Const.ACC_INTERFACE, flag); } + /** + * Tests whether the native bit is on. + * + * @return whether the native bit is on. + */ public final boolean isNative() { - return (access_flags & Const.ACC_NATIVE) != 0; + return test(Const.ACC_NATIVE); } + /** + * Sets the native bit. + * + * @param flag The new value. + */ public final void isNative(final boolean flag) { setFlag(Const.ACC_NATIVE, flag); } + /** + * Tests whether the private bit is on. + * + * @return whether the private bit is on. + */ public final boolean isPrivate() { - return (access_flags & Const.ACC_PRIVATE) != 0; + return test(Const.ACC_PRIVATE); } + /** + * Sets the private bit. + * + * @param flag The new value. + */ public final void isPrivate(final boolean flag) { setFlag(Const.ACC_PRIVATE, flag); } + /** + * Tests whether the protected bit is on. + * + * @return whether the protected bit is on. + */ public final boolean isProtected() { - return (access_flags & Const.ACC_PROTECTED) != 0; + return test(Const.ACC_PROTECTED); } + /** + * Sets the protected bit. + * + * @param flag The new value. + */ public final void isProtected(final boolean flag) { setFlag(Const.ACC_PROTECTED, flag); } + /** + * Tests whether the public bit is on. + * + * @return whether the public bit is on. + */ public final boolean isPublic() { - return (access_flags & Const.ACC_PUBLIC) != 0; + return test(Const.ACC_PUBLIC); } + /** + * Sets the public bit. + * + * @param flag The new value. + */ public final void isPublic(final boolean flag) { setFlag(Const.ACC_PUBLIC, flag); } + /** + * Tests whether the static bit is on. + * + * @return whether the static bit is on. + */ public final boolean isStatic() { - return (access_flags & Const.ACC_STATIC) != 0; + return test(Const.ACC_STATIC); } + /** + * Sets the static bit. + * + * @param flag The new value. + */ public final void isStatic(final boolean flag) { setFlag(Const.ACC_STATIC, flag); } + /** + * Tests whether the strict bit is on. + * + * @return whether the strict bit is on. + */ public final boolean isStrictfp() { - return (access_flags & Const.ACC_STRICT) != 0; + return test(Const.ACC_STRICT); } + /** + * Sets the strict bit. + * + * @param flag The new value. + */ public final void isStrictfp(final boolean flag) { setFlag(Const.ACC_STRICT, flag); } + /** + * Tests whether the synchronized bit is on. + * + * @return whether the synchronized bit is on. + */ public final boolean isSynchronized() { - return (access_flags & Const.ACC_SYNCHRONIZED) != 0; + return test(Const.ACC_SYNCHRONIZED); } + /** + * Sets the synchronized bit. + * + * @param flag The new value. + */ public final void isSynchronized(final boolean flag) { setFlag(Const.ACC_SYNCHRONIZED, flag); } + /** + * Tests whether the synthetic bit is on. + * + * @return whether the synthetic bit is on. + */ public final boolean isSynthetic() { - return (access_flags & Const.ACC_SYNTHETIC) != 0; + return test(Const.ACC_SYNTHETIC); } + /** + * Sets the synthetic bit. + * + * @param flag The new value. + */ public final void isSynthetic(final boolean flag) { setFlag(Const.ACC_SYNTHETIC, flag); } + /** + * Tests whether the transient bit is on. + * + * @return whether the varargs bit is on. + */ public final boolean isTransient() { - return (access_flags & Const.ACC_TRANSIENT) != 0; + return test(Const.ACC_TRANSIENT); } + /** + * Sets the varargs bit. + * + * @param flag The new value. + */ public final void isTransient(final boolean flag) { setFlag(Const.ACC_TRANSIENT, flag); } + /** + * Tests whether the varargs bit is on. + * + * @return whether the varargs bit is on. + */ public final boolean isVarArgs() { - return (access_flags & Const.ACC_VARARGS) != 0; + return test(Const.ACC_VARARGS); } + /** + * Sets the varargs bit. + * + * @param flag The new value. + */ public final void isVarArgs(final boolean flag) { setFlag(Const.ACC_VARARGS, flag); } + /** + * Tests whether the volatile bit is on. + * + * @return whether the volatile bit is on. + */ public final boolean isVolatile() { - return (access_flags & Const.ACC_VOLATILE) != 0; + return test(Const.ACC_VOLATILE); } + /** + * Sets the volatile bit. + * + * @param flag The new value. + */ public final void isVolatile(final boolean flag) { setFlag(Const.ACC_VOLATILE, flag); } /** - * Set access flags aka "modifiers". + * Sets access flags also known as modifiers. * * @param accessFlags Access flags of the object. */ @@ -207,11 +377,21 @@ public abstract class AccessFlags { } /** - * Set access flags aka "modifiers". + * Sets access flags aka "modifiers". * * @param accessFlags Access flags of the object. */ public final void setModifiers(final int accessFlags) { setAccessFlags(accessFlags); } + + /** + * Tests whether the bit is on. + * + * @param test the bit to test. + * @return whether the bit is on. + */ + private boolean test(final short test) { + return (access_flags & test) != 0; + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/AnnotationEntry.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/AnnotationEntry.java index 466e9bf3404..c9503332a6f 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/AnnotationEntry.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/AnnotationEntry.java @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -27,20 +26,22 @@ import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.stream.Stream; +import jdk.xml.internal.Utils; /** * Represents one annotation in the annotation table * * @since 6.0 + * @LastModified: Sept 2025 */ public class AnnotationEntry implements Node { public static final AnnotationEntry[] EMPTY_ARRAY = {}; - public static AnnotationEntry[] createAnnotationEntries(final Attribute[] attrs) { + public static AnnotationEntry[] createAnnotationEntries(final Attribute[] attributes) { // Find attributes that contain annotation data - return Stream.of(attrs).filter(Annotations.class::isInstance).flatMap(e -> Stream.of(((Annotations) e).getAnnotationEntries())) - .toArray(AnnotationEntry[]::new); + return Utils.streamOfIfNonNull(attributes).filter(Annotations.class::isInstance).flatMap(e -> Stream.of(((Annotations) e).getAnnotationEntries())) + .toArray(AnnotationEntry[]::new); } /** @@ -55,7 +56,6 @@ public class AnnotationEntry implements Node { public static AnnotationEntry read(final DataInput input, final ConstantPool constantPool, final boolean isRuntimeVisible) throws IOException { final AnnotationEntry annotationEntry = new AnnotationEntry(input.readUnsignedShort(), constantPool, isRuntimeVisible); final int numElementValuePairs = input.readUnsignedShort(); - annotationEntry.elementValuePairs = new ArrayList<>(); for (int i = 0; i < numElementValuePairs; i++) { annotationEntry.elementValuePairs .add(new ElementValuePair(input.readUnsignedShort(), ElementValue.readElementValue(input, constantPool), constantPool)); @@ -69,12 +69,13 @@ public class AnnotationEntry implements Node { private final boolean isRuntimeVisible; - private List elementValuePairs; + private final List elementValuePairs; public AnnotationEntry(final int typeIndex, final ConstantPool constantPool, final boolean isRuntimeVisible) { this.typeIndex = typeIndex; this.constantPool = constantPool; this.isRuntimeVisible = isRuntimeVisible; + this.elementValuePairs = new ArrayList<>(); } /** diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Annotations.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Annotations.java index 52ac9d0dd98..6ff9b4a046f 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Annotations.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Annotations.java @@ -52,7 +52,7 @@ public abstract class Annotations extends Attribute implements Iterable The class File Format : * The BootstrapMethods Attribute * @since 6.0 + * @LastModified: Sept 2025 */ public class BootstrapMethod implements Cloneable { + static final BootstrapMethod[] EMPTY_ARRAY = {}; + /** Index of the CONSTANT_MethodHandle_info structure in the constant_pool table */ private int bootstrapMethodRef; @@ -54,7 +57,7 @@ public class BootstrapMethod implements Cloneable { } /** - * Construct object from input stream. + * Constructs object from input stream. * * @param input Input stream * @throws IOException if an I/O error occurs. @@ -78,7 +81,7 @@ public class BootstrapMethod implements Cloneable { */ public BootstrapMethod(final int bootstrapMethodRef, final int[] bootstrapArguments) { this.bootstrapMethodRef = bootstrapMethodRef; - this.bootstrapArguments = bootstrapArguments; + setBootstrapArguments(bootstrapArguments); } /** @@ -87,7 +90,7 @@ public class BootstrapMethod implements Cloneable { public BootstrapMethod copy() { try { return (BootstrapMethod) clone(); - } catch (final CloneNotSupportedException e) { + } catch (final CloneNotSupportedException ignore) { // TODO should this throw? } return null; @@ -132,7 +135,7 @@ public class BootstrapMethod implements Cloneable { * @param bootstrapArguments int[] indices into constant_pool of CONSTANT_[type]_info */ public void setBootstrapArguments(final int[] bootstrapArguments) { - this.bootstrapArguments = bootstrapArguments; + this.bootstrapArguments = Utils.createEmptyArrayIfNull(bootstrapArguments); } /** diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/BootstrapMethods.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/BootstrapMethods.java index 6f9930f1b16..ef2475e1856 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/BootstrapMethods.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/BootstrapMethods.java @@ -58,11 +58,11 @@ public class BootstrapMethods extends Attribute implements Iterable - * Note that the detail message associated with {@code cause} is not automatically incorporated in this runtime exception's detail message. * * @param message the detail message (which is saved for later retrieval by the {@link #getMessage()} method). - * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method). (A {@code null} value is permitted, and indicates that - * the cause is nonexistent or unknown.) + * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method). A {@code null} value is permitted, and indicates that + * the cause is nonexistent or unknown. * @since 6.0 */ public ClassFormatException(final String message, final Throwable cause) { @@ -63,8 +61,8 @@ public class ClassFormatException extends RuntimeException { * Constructs a new instance with the specified cause and a detail message of {@code (cause==null ? null : cause.toString())} (which typically contains the * class and detail message of {@code cause}). This constructor is useful for runtime exceptions that are little more than wrappers for other throwables. * - * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method). (A {@code null} value is permitted, and indicates that the - * cause is nonexistent or unknown.) + * @param cause the cause (which is saved for later retrieval by the {@link #getCause()} method). A {@code null} value is permitted, and indicates that the + * cause is nonexistent or unknown. * @since 6.7.0 */ public ClassFormatException(final Throwable cause) { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ClassParser.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ClassParser.java index c9daaeabf9b..0dbda722ec4 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ClassParser.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ClassParser.java @@ -37,7 +37,7 @@ import com.sun.org.apache.bcel.internal.Const; * appropriate exception is propagated back to the caller. * * The structure and the names comply, except for a few conveniences, exactly with the - * JVM specification 1.0. See this paper for further details about + * JVM specification 1.0. See this paper for further details about * the structure of a bytecode file. */ public final class ClassParser { @@ -57,7 +57,7 @@ public final class ClassParser { private Field[] fields; // class fields, i.e., its variables private Method[] methods; // methods defined in the class private Attribute[] attributes; // attributes defined in the class - private final boolean isZip; // Loaded from zip file + private final boolean isZip; // Loaded from ZIP file /** * Parses class from the given stream. @@ -91,7 +91,7 @@ public final class ClassParser { /** * Parses class from given .class file in a ZIP-archive * - * @param zipFile zip file name + * @param zipFile ZIP file name * @param fileName file name */ public ClassParser(final String zipFile, final String fileName) { @@ -104,7 +104,7 @@ public final class ClassParser { /** * Parses the given Java class file and return an object that represents the contained data, i.e., constants, methods, * fields and commands. A ClassFormatException is raised, if the file is not a valid .class file. (This does - * not include verification of the byte code as it is performed by the java interpreter). + * not include verification of the byte code as it is performed by the Java interpreter). * * @return Class object representing the parsed class file * @throws IOException if an I/O error occurs. @@ -151,11 +151,11 @@ public final class ClassParser { // for (int i=0; i < u.length; i++) // System.err.println("WARNING: " + u[i]); // Everything should have been read now - // if(file.available() > 0) { + // if (file.available() > 0) { // int bytes = file.available(); // byte[] buf = new byte[bytes]; // file.read(buf); - // if(!(isZip && (buf.length == 1))) { + // if (!(isZip && (buf.length == 1))) { // System.err.println("WARNING: Trailing garbage at end of " + fileName); // System.err.println(bytes + " extra bytes: " + Utility.toHexString(buf)); // } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Code.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Code.java index 498a8c71b18..7573a5412e7 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Code.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Code.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -27,6 +27,7 @@ import java.util.Arrays; import com.sun.org.apache.bcel.internal.Const; import com.sun.org.apache.bcel.internal.util.Args; +import jdk.xml.internal.Utils; /** * This class represents a chunk of Java byte code contained in a method. It is instantiated by the @@ -59,7 +60,7 @@ import com.sun.org.apache.bcel.internal.util.Args; * @see CodeException * @see LineNumberTable * @see LocalVariableTable - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public final class Code extends Attribute { @@ -93,7 +94,7 @@ public final class Code extends Attribute { code = new byte[codeLength]; // Read byte code file.readFully(code); /* - * Read exception table that contains all regions where an exception handler is active, i.e., a try { ... } catch() + * Read exception table that contains all regions where an exception handler is active, i.e., a try { ... } catch () * block. */ final int exceptionTableLength = file.readUnsignedShort(); @@ -107,7 +108,7 @@ public final class Code extends Attribute { final int attributesCount = file.readUnsignedShort(); attributes = new Attribute[attributesCount]; for (int i = 0; i < attributesCount; i++) { - attributes[i] = Attribute.readAttribute(file, constantPool); + attributes[i] = readAttribute(file, constantPool); } /* * Adjust length, because of setAttributes in this(), s.b. length is incorrect, because it didn't take the internal @@ -131,8 +132,8 @@ public final class Code extends Attribute { super(Const.ATTR_CODE, nameIndex, length, constantPool); this.maxStack = Args.requireU2(maxStack, "maxStack"); this.maxLocals = Args.requireU2(maxLocals, "maxLocals"); - this.code = code != null ? code : Const.EMPTY_BYTE_ARRAY; - this.exceptionTable = exceptionTable != null ? exceptionTable : CodeException.EMPTY_CODE_EXCEPTION_ARRAY; + this.code = Utils.createEmptyArrayIfNull(code); + this.exceptionTable = Utils.createEmptyArrayIfNull(exceptionTable, CodeException[].class); Args.requireU2(this.exceptionTable.length, "exceptionTable.length"); this.attributes = attributes != null ? attributes : EMPTY_ARRAY; super.setLength(calculateLength()); // Adjust length @@ -263,6 +264,20 @@ public final class Code extends Attribute { return null; } + /** + * Gets the local variable type table attribute {@link LocalVariableTypeTable}. + * @return LocalVariableTypeTable of Code, if it has one, null otherwise. + * @since 6.10.0 + */ + public LocalVariableTypeTable getLocalVariableTypeTable() { + for (final Attribute attribute : attributes) { + if (attribute instanceof LocalVariableTypeTable) { + return (LocalVariableTypeTable) attribute; + } + } + return null; + } + /** * @return Number of local variables. */ @@ -277,6 +292,20 @@ public final class Code extends Attribute { return maxStack; } + /** + * Finds the attribute of {@link StackMap} instance. + * @return StackMap of Code, if it has one, else null. + * @since 6.8.0 + */ + public StackMap getStackMap() { + for (final Attribute attribute : attributes) { + if (attribute instanceof StackMap) { + return (StackMap) attribute; + } + } + return null; + } + /** * @param attributes the attributes to set for this Code */ @@ -289,7 +318,7 @@ public final class Code extends Attribute { * @param code byte code */ public void setCode(final byte[] code) { - this.code = code != null ? code : Const.EMPTY_BYTE_ARRAY; + this.code = Utils.createEmptyArrayIfNull(code); super.setLength(calculateLength()); // Adjust length } @@ -297,7 +326,7 @@ public final class Code extends Attribute { * @param exceptionTable exception table */ public void setExceptionTable(final CodeException[] exceptionTable) { - this.exceptionTable = exceptionTable != null ? exceptionTable : CodeException.EMPTY_CODE_EXCEPTION_ARRAY; + this.exceptionTable = exceptionTable != null ? exceptionTable : CodeException.EMPTY_ARRAY; super.setLength(calculateLength()); // Adjust length } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/CodeException.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/CodeException.java index ee224e6b348..b8bf109239e 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/CodeException.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/CodeException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -52,19 +52,19 @@ import com.sun.org.apache.bcel.internal.util.Args; *
* * @see Code - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public final class CodeException implements Cloneable, Node { /** * Empty array. */ - static final CodeException[] EMPTY_CODE_EXCEPTION_ARRAY = {}; + static final CodeException[] EMPTY_ARRAY = {}; /** Range in the code the exception handler. */ private int startPc; - /** active. startPc is inclusive, endPc exclusive. */ + /** Active. startPc is inclusive, endPc exclusive. */ private int endPc; /** diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Constant.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Constant.java index 885e1b599eb..9b3d6f31e17 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Constant.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Constant.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -32,30 +32,29 @@ import com.sun.org.apache.bcel.internal.util.BCELComparator; * in the constant pool of a class file. The classes keep closely to * the JVM specification. * - * @LastModified: May 2021 + * @LastModified: Sept 2025 */ public abstract class Constant implements Cloneable, Node { - private static BCELComparator bcelComparator = new BCELComparator() { + static final Constant[] EMPTY_ARRAY = {}; + + private static BCELComparator bcelComparator = new BCELComparator() { @Override - public boolean equals(final Object o1, final Object o2) { - final Constant THIS = (Constant) o1; - final Constant THAT = (Constant) o2; - return Objects.equals(THIS.toString(), THAT.toString()); + public boolean equals(final Constant a, final Constant b) { + return a == b || a != null && b != null && Objects.equals(a.toString(), b.toString()); } @Override - public int hashCode(final Object o) { - final Constant THIS = (Constant) o; - return THIS.toString().hashCode(); + public int hashCode(final Constant o) { + return o != null ? Objects.hashCode(o.toString()) : 0; } }; /** - * @return Comparison strategy object + * @return Comparison strategy object. */ - public static BCELComparator getComparator() { + public static BCELComparator getComparator() { return bcelComparator; } @@ -113,7 +112,7 @@ public abstract class Constant implements Cloneable, Node { /** * @param comparator Comparison strategy object */ - public static void setComparator(final BCELComparator comparator) { + public static void setComparator(final BCELComparator comparator) { bcelComparator = comparator; } @@ -148,7 +147,7 @@ public abstract class Constant implements Cloneable, Node { try { return super.clone(); } catch (final CloneNotSupportedException e) { - throw new Error("Clone Not Supported"); // never happens + throw new UnsupportedOperationException("Clone Not Supported", e); // never happens } } @@ -174,7 +173,7 @@ public abstract class Constant implements Cloneable, Node { */ @Override public boolean equals(final Object obj) { - return bcelComparator.equals(this, obj); + return obj instanceof Constant && bcelComparator.equals(this, (Constant) obj); } /** @@ -185,7 +184,7 @@ public abstract class Constant implements Cloneable, Node { } /** - * Returns value as defined by given BCELComparator strategy. By default return the hashcode of the result of + * Returns value as defined by given BCELComparator strategy. By default return the hash code of the result of * toString(). * * @see Object#hashCode() diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantCP.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantCP.java index 71fd91b249a..51113a1aeaa 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantCP.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantCP.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -28,11 +28,11 @@ import com.sun.org.apache.bcel.internal.Const; /** * Abstract super class for Fieldref, Methodref, InterfaceMethodref and InvokeDynamic constants. * - * @see ConstantFieldref - * @see ConstantMethodref - * @see ConstantInterfaceMethodref - * @see ConstantInvokeDynamic - * @LastModified: Jun 2019 + * @see ConstantFieldref + * @see ConstantMethodref + * @see ConstantInterfaceMethodref + * @see ConstantInvokeDynamic + * @LastModified: Sept 2025 */ public abstract class ConstantCP extends Constant { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantDouble.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantDouble.java index ebb3d0af46a..14b43937c92 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantDouble.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantDouble.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -29,8 +29,8 @@ import com.sun.org.apache.bcel.internal.Const; /** * This class is derived from the abstract {@link Constant} and represents a reference to a Double object. * - * @see Constant - * @LastModified: Jun 2019 + * @see Constant + * @LastModified: Sept 2025 */ public final class ConstantDouble extends Constant implements ConstantObject { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantFloat.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantFloat.java index 9c30c9e4fdb..e86bbb94e66 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantFloat.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantFloat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -29,8 +29,8 @@ import com.sun.org.apache.bcel.internal.Const; /** * This class is derived from the abstract {@link Constant} and represents a reference to a float object. * - * @see Constant - * @LastModified: Jun 2019 + * @see Constant + * @LastModified: Sept 2025 */ public final class ConstantFloat extends Constant implements ConstantObject { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantInteger.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantInteger.java index cabd2e15b03..20c0717acb6 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantInteger.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantInteger.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -29,8 +29,8 @@ import com.sun.org.apache.bcel.internal.Const; /** * This class is derived from the abstract {@link Constant} and represents a reference to an int object. * - * @see Constant - * @LastModified: Jun 2019 + * @see Constant + * @LastModified: Sept 2025 */ public final class ConstantInteger extends Constant implements ConstantObject { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantLong.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantLong.java index c1e683abadb..6936162c264 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantLong.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantLong.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -29,8 +29,8 @@ import com.sun.org.apache.bcel.internal.Const; /** * This class is derived from the abstract {@link Constant} and represents a reference to a long object. * - * @see Constant - * @LastModified: Jan 2020 + * @see Constant + * @LastModified: Sept 2025 */ public final class ConstantLong extends Constant implements ConstantObject { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantObject.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantObject.java index cb28f7dacb8..ab187b7e4f8 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantObject.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantObject.java @@ -29,7 +29,10 @@ package com.sun.org.apache.bcel.internal.classfile; public interface ConstantObject { /** - * @return object representing the constant, e.g., Long for ConstantLong + * Gets the object representing the constant, e.g., Long for ConstantLong. + * + * @param constantPool the constant. + * @return object representing the constant, e.g., Long for ConstantLong. */ - Object getConstantValue(ConstantPool cp); + Object getConstantValue(ConstantPool constantPool); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantPool.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantPool.java index 5fb4ef1b080..ae1e3977c99 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantPool.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantPool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -35,7 +35,7 @@ import com.sun.org.apache.bcel.internal.Const; * * @see Constant * @see com.sun.org.apache.bcel.internal.generic.ConstantPoolGen - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public class ConstantPool implements Cloneable, Node, Iterable { @@ -73,7 +73,7 @@ public class ConstantPool implements Cloneable, Node, Iterable { * @param constantPool Array of constants */ public ConstantPool(final Constant[] constantPool) { - this.constantPool = constantPool; + setConstantPool(constantPool); } /** @@ -88,6 +88,7 @@ public class ConstantPool implements Cloneable, Node, Iterable { constantPool = new Constant[constantPoolCount]; /* * constantPool[0] is unused by the compiler and may be used freely by the implementation. + * constantPool[0] is currently unused by the implementation. */ for (int i = 1; i < constantPoolCount; i++) { constantPool[i] = Constant.readConstant(input); @@ -288,7 +289,7 @@ public class ConstantPool implements Cloneable, Node, Iterable { */ public T getConstant(final int index, final byte tag, final Class castTo) throws ClassFormatException { final T c = getConstant(index); - if (c.getTag() != tag) { + if (c == null || c.getTag() != tag) { throw new ClassFormatException("Expected class '" + Const.getConstantName(tag) + "' at index " + index + " and got " + c); } return c; @@ -313,15 +314,17 @@ public class ConstantPool implements Cloneable, Node, Iterable { throw new ClassFormatException("Invalid constant pool reference at index: " + index + ". Expected " + castTo + " but was " + constantPool[index].getClass()); } + if (index > 1) { + final Constant prev = constantPool[index - 1]; + if (prev != null && (prev.getTag() == Const.CONSTANT_Double || prev.getTag() == Const.CONSTANT_Long)) { + throw new ClassFormatException("Constant pool at index " + index + " is invalid. The index is unused due to the preceeding " + + Const.getConstantName(prev.getTag()) + "."); + } + } // Previous check ensures this won't throw a ClassCastException final T c = castTo.cast(constantPool[index]); - if (c == null - // the 0th element is always null - && index != 0) { - final Constant prev = constantPool[index - 1]; - if (prev == null || prev.getTag() != Const.CONSTANT_Double && prev.getTag() != Const.CONSTANT_Long) { - throw new ClassFormatException("Constant pool at index " + index + " is null."); - } + if (c == null) { + throw new ClassFormatException("Constant pool at index " + index + " is null."); } return c; } @@ -402,7 +405,7 @@ public class ConstantPool implements Cloneable, Node, Iterable { * @return Length of constant pool. */ public int getLength() { - return constantPool == null ? 0 : constantPool.length; + return constantPool.length; } @Override @@ -421,7 +424,7 @@ public class ConstantPool implements Cloneable, Node, Iterable { * @param constantPool */ public void setConstantPool(final Constant[] constantPool) { - this.constantPool = constantPool; + this.constantPool = constantPool != null ? constantPool : Constant.EMPTY_ARRAY; } /** diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantUtf8.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantUtf8.java index ec875554c1a..90e45c807e5 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantUtf8.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantUtf8.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -36,11 +36,11 @@ import com.sun.org.apache.bcel.internal.Const; * The following system properties govern caching this class performs. *

*
    - *
  • {@value #SYS_PROP_CACHE_MAX_ENTRIES} (since 6.4): The size of the cache, by default 0, meaning caching is + *
  • {@link #SYS_PROP_CACHE_MAX_ENTRIES} (since 6.4): The size of the cache, by default 0, meaning caching is * disabled.
  • - *
  • {@value #SYS_PROP_CACHE_MAX_ENTRY_SIZE} (since 6.0): The maximum size of the values to cache, by default 200, 0 + *
  • {@link #SYS_PROP_CACHE_MAX_ENTRY_SIZE} (since 6.0): The maximum size of the values to cache, by default 200, 0 * disables caching. Values larger than this are not cached.
  • - *
  • {@value #SYS_PROP_STATISTICS} (since 6.0): Prints statistics on the console when the JVM exits.
  • + *
  • {@link #SYS_PROP_STATISTICS} (since 6.0): Prints statistics on the console when the JVM exits.
  • *
*

* Here is a sample Maven invocation with caching disabled: @@ -58,11 +58,11 @@ import com.sun.org.apache.bcel.internal.Const; * * * @see Constant - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public final class ConstantUtf8 extends Constant { - private static class Cache { + private static final class Cache { private static final boolean BCEL_STATISTICS = false; private static final int MAX_ENTRIES = 20000; @@ -82,7 +82,7 @@ public final class ConstantUtf8 extends Constant { private static final int MAX_ENTRY_SIZE = 200; static boolean isEnabled() { - return Cache.MAX_ENTRIES > 0 && MAX_ENTRY_SIZE > 0; + return MAX_ENTRIES > 0 && MAX_ENTRY_SIZE > 0; } } @@ -117,6 +117,11 @@ public final class ConstantUtf8 extends Constant { hits = considered = skipped = created = 0; } + // Avoid Spotbugs complaint about Write to static field + private static void countCreated() { + created++; + } + /** * Gets a new or cached instance of the given value. *

@@ -203,7 +208,7 @@ public final class ConstantUtf8 extends Constant { ConstantUtf8(final DataInput dataInput) throws IOException { super(Const.CONSTANT_Utf8); value = dataInput.readUTF(); - created++; + countCreated(); } /** @@ -212,7 +217,7 @@ public final class ConstantUtf8 extends Constant { public ConstantUtf8(final String value) { super(Const.CONSTANT_Utf8); this.value = Objects.requireNonNull(value, "value"); - created++; + countCreated(); } /** diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantValue.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantValue.java index 311e9a33fa3..143c2a25544 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantValue.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ConstantValue.java @@ -56,7 +56,7 @@ public final class ConstantValue extends Attribute { } /** - * Construct object from input stream. + * Constructs object from input stream. * * @param nameIndex Name index in constant pool * @param length Content length in bytes diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Deprecated.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Deprecated.java index 90841d96081..c561afe33c5 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Deprecated.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Deprecated.java @@ -59,7 +59,7 @@ public final class Deprecated extends Attribute { } /** - * Construct object from input stream. + * Constructs object from input stream. * * @param nameIndex Index in constant pool to CONSTANT_Utf8 * @param length Content length in bytes diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/DescendingVisitor.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/DescendingVisitor.java index 3c475891acd..934b608d6ac 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/DescendingVisitor.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/DescendingVisitor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -22,12 +22,13 @@ package com.sun.org.apache.bcel.internal.classfile; import java.util.Objects; import java.util.Stack; import java.util.stream.Stream; +import jdk.xml.internal.Utils; /** - * Traverses a JavaClass with another Visitor object 'piggy-backed' that is - * applied to all components of a JavaClass object. I.e. this class supplies the - * traversal strategy, other classes can make use of it. + * Traverses a JavaClass with another Visitor object 'piggy-backed' that is applied to all components of a JavaClass + * object. I.e. this class supplies the traversal strategy, other classes can make use of it. * + * @LastModified: Sept 2025 */ public class DescendingVisitor implements Visitor { private final JavaClass clazz; @@ -46,7 +47,7 @@ public class DescendingVisitor implements Visitor { } private void accept(final E[] node) { - Stream.of(node).forEach(e -> e.accept(this)); + Utils.streamOfIfNonNull(node).forEach(e -> e.accept(this)); } /** @@ -507,6 +508,21 @@ public class DescendingVisitor implements Visitor { stack.pop(); } + @Override + public void visitRecord(final Record record) { + stack.push(record); + record.accept(visitor); + accept(record.getComponents()); + stack.pop(); + } + + @Override + public void visitRecordComponent(final RecordComponentInfo recordComponentInfo) { + stack.push(recordComponentInfo); + recordComponentInfo.accept(visitor); + stack.pop(); + } + @Override public void visitSignature(final Signature attribute) { stack.push(attribute); @@ -531,6 +547,20 @@ public class DescendingVisitor implements Visitor { @Override public void visitStackMapEntry(final StackMapEntry var) { + stack.push(var); + var.accept(visitor); + accept(var.getTypesOfLocals()); + accept(var.getTypesOfStackItems()); + stack.pop(); + } + + /** + * Visits a {@link StackMapType} object. + * @param var object to visit + * @since 6.8.0 + */ + @Override + public void visitStackMapType(final StackMapType var) { stack.push(var); var.accept(visitor); stack.pop(); @@ -549,4 +579,5 @@ public class DescendingVisitor implements Visitor { attribute.accept(visitor); stack.pop(); } + } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ElementValue.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ElementValue.java index 5c3d9b3172b..d87307c0e7d 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ElementValue.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ElementValue.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -50,7 +50,7 @@ import com.sun.org.apache.bcel.internal.Const; *} * * @since 6.0 - * @LastModified: May 2021 + * @LastModified: Sept 2025 */ public abstract class ElementValue { @@ -67,6 +67,7 @@ public abstract class ElementValue { public static final byte PRIMITIVE_LONG = 'J'; public static final byte PRIMITIVE_SHORT = 'S'; public static final byte PRIMITIVE_BOOLEAN = 'Z'; + static final ElementValue[] EMPTY_ARRAY = {}; /** * Reads an {@code element_value} as an {@code ElementValue}. @@ -124,7 +125,7 @@ public abstract class ElementValue { final int numArrayVals = input.readUnsignedShort(); final ElementValue[] evalues = new ElementValue[numArrayVals]; for (int j = 0; j < numArrayVals; j++) { - evalues[j] = ElementValue.readElementValue(input, cpool, arrayNesting); + evalues[j] = readElementValue(input, cpool, arrayNesting); } return new ArrayElementValue(ARRAY, evalues, cpool); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/EmptyVisitor.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/EmptyVisitor.java index 826ba41af70..db33c871656 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/EmptyVisitor.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/EmptyVisitor.java @@ -315,6 +315,15 @@ public class EmptyVisitor implements Visitor { public void visitStackMapEntry(final StackMapEntry obj) { } + /** + * Visits a {@link StackMapType} object. + * @param obj object to visit + * @since 6.8.0 + */ + @Override + public void visitStackMapType(final StackMapType obj) { + } + @Override public void visitSynthetic(final Synthetic obj) { } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ExceptionTable.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ExceptionTable.java index 90eaa3eb062..1b6004b3740 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ExceptionTable.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ExceptionTable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -27,6 +27,7 @@ import java.util.Arrays; import com.sun.org.apache.bcel.internal.Const; import com.sun.org.apache.bcel.internal.util.Args; +import jdk.xml.internal.Utils; /** * This class represents the table of exceptions that are thrown by a method. This attribute may be used once per @@ -43,7 +44,7 @@ import com.sun.org.apache.bcel.internal.util.Args; * } * * @see Code - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public final class ExceptionTable extends Attribute { @@ -60,7 +61,7 @@ public final class ExceptionTable extends Attribute { } /** - * Construct object from input stream. + * Constructs object from input stream. * * @param nameIndex Index in constant pool * @param length Content length in bytes @@ -85,7 +86,7 @@ public final class ExceptionTable extends Attribute { */ public ExceptionTable(final int nameIndex, final int length, final int[] exceptionIndexTable, final ConstantPool constantPool) { super(Const.ATTR_EXCEPTIONS, nameIndex, length, constantPool); - this.exceptionIndexTable = exceptionIndexTable != null ? exceptionIndexTable : Const.EMPTY_INT_ARRAY; + this.exceptionIndexTable = Utils.createEmptyArrayIfNull(exceptionIndexTable); Args.requireU2(this.exceptionIndexTable.length, "exceptionIndexTable.length"); } @@ -156,7 +157,7 @@ public final class ExceptionTable extends Attribute { * length. */ public void setExceptionIndexTable(final int[] exceptionIndexTable) { - this.exceptionIndexTable = exceptionIndexTable != null ? exceptionIndexTable : Const.EMPTY_INT_ARRAY; + this.exceptionIndexTable = Utils.createEmptyArrayIfNull(exceptionIndexTable); } /** diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Field.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Field.java index 7e6ccb2ecb5..8ffc796a0ea 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Field.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Field.java @@ -42,45 +42,37 @@ public final class Field extends FieldOrMethod { */ public static final Field[] EMPTY_ARRAY = {}; - private static BCELComparator bcelComparator = new BCELComparator() { + private static BCELComparator bcelComparator = new BCELComparator() { @Override - public boolean equals(final Object o1, final Object o2) { - final Field THIS = (Field) o1; - final Field THAT = (Field) o2; - return Objects.equals(THIS.getName(), THAT.getName()) && Objects.equals(THIS.getSignature(), THAT.getSignature()); + public boolean equals(final Field a, final Field b) { + return a == b || a != null && b != null && Objects.equals(a.getName(), b.getName()) && Objects.equals(a.getSignature(), b.getSignature()); } @Override - public int hashCode(final Object o) { - final Field THIS = (Field) o; - return THIS.getSignature().hashCode() ^ THIS.getName().hashCode(); + public int hashCode(final Field o) { + return o != null ? Objects.hash(o.getSignature(), o.getName()) : 0; } }; /** - * Empty array. + * @return Comparison strategy object. */ - static final Field[] EMPTY_FIELD_ARRAY = {}; - - /** - * @return Comparison strategy object - */ - public static BCELComparator getComparator() { + public static BCELComparator getComparator() { return bcelComparator; } /** - * @param comparator Comparison strategy object + * @param comparator Comparison strategy object. */ - public static void setComparator(final BCELComparator comparator) { + public static void setComparator(final BCELComparator comparator) { bcelComparator = comparator; } /** - * Construct object from file stream. + * Constructs object from file stream. * - * @param file Input stream + * @param file Input stream. */ Field(final DataInput file, final ConstantPool constantPool) throws IOException, ClassFormatException { super(file, constantPool); @@ -133,7 +125,7 @@ public final class Field extends FieldOrMethod { */ @Override public boolean equals(final Object obj) { - return bcelComparator.equals(this, obj); + return obj instanceof Field && bcelComparator.equals(this, (Field) obj); } /** @@ -149,14 +141,16 @@ public final class Field extends FieldOrMethod { } /** + * See https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.2.2 + * * @return type of field */ public Type getType() { - return Type.getReturnType(getSignature()); + return Type.getType(getSignature()); } /** - * Return value as defined by given BCELComparator strategy. By default return the hashcode of the field's name XOR + * Return value as defined by given BCELComparator strategy. By default return the hash code of the field's name XOR * signature. * * @see Object#hashCode() diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/FieldOrMethod.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/FieldOrMethod.java index 1daa6a62fd5..679d5a9eb7c 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/FieldOrMethod.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/FieldOrMethod.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -28,7 +28,7 @@ import java.util.Arrays; /** * Abstract super class for fields and methods. * - * @LastModified: Jan 2020 + * @LastModified: Sept 2025 */ public abstract class FieldOrMethod extends AccessFlags implements Cloneable, Node { @@ -72,7 +72,7 @@ public abstract class FieldOrMethod extends AccessFlags implements Cloneable, No } /** - * Construct object from file stream. + * Constructs object from file stream. * * @param file Input stream * @throws IOException if an I/O error occurs. @@ -88,7 +88,7 @@ public abstract class FieldOrMethod extends AccessFlags implements Cloneable, No } /** - * Construct object from file stream. + * Constructs object from file stream. * * @param file Input stream * @throws IOException if an I/O error occurs. @@ -137,7 +137,7 @@ public abstract class FieldOrMethod extends AccessFlags implements Cloneable, No Arrays.setAll(c.attributes, i -> attributes[i].copy(constantPool)); return c; } catch (final CloneNotSupportedException e) { - throw new IllegalStateException(e); + throw new UnsupportedOperationException(e); } } @@ -152,10 +152,8 @@ public abstract class FieldOrMethod extends AccessFlags implements Cloneable, No file.writeShort(name_index); file.writeShort(signature_index); file.writeShort(attributes_count); - if (attributes != null) { - for (final Attribute attribute : attributes) { - attribute.dump(file); - } + for (final Attribute attribute : attributes) { + attribute.dump(file); } } @@ -171,6 +169,22 @@ public abstract class FieldOrMethod extends AccessFlags implements Cloneable, No return annotationEntries; } + /** + * Gets attribute for given tag. + * @return Attribute for given tag, null if not found. + * Refer to {@link com.sun.org.apache.bcel.internal.Const#ATTR_UNKNOWN} constants named ATTR_* for possible values. + * @since 6.10.0 + */ + @SuppressWarnings("unchecked") + public final T getAttribute(final byte tag) { + for (final Attribute attribute : getAttributes()) { + if (attribute.getTag() == tag) { + return (T) attribute; + } + } + return null; + } + /** * @return Collection of object attributes. */ @@ -221,7 +235,7 @@ public abstract class FieldOrMethod extends AccessFlags implements Cloneable, No } /** - * @return String representation of object's type signature (java style) + * @return String representation of object's type signature (Java style) */ public final String getSignature() { return constant_pool.getConstantUtf8(signature_index).getBytes(); @@ -238,8 +252,8 @@ public abstract class FieldOrMethod extends AccessFlags implements Cloneable, No * @param attributes Collection of object attributes. */ public final void setAttributes(final Attribute[] attributes) { - this.attributes = attributes; - this.attributes_count = attributes != null ? attributes.length : 0; // init deprecated field + this.attributes = attributes != null ? attributes : Attribute.EMPTY_ARRAY; + this.attributes_count = this.attributes.length; // init deprecated field } /** diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClass.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClass.java index d77582815b7..82900dcca10 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClass.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClass.java @@ -41,7 +41,7 @@ public final class InnerClass implements Cloneable, Node { private int innerAccessFlags; /** - * Construct object from file stream. + * Constructs object from file stream. * * @param file Input stream * @throws IOException if an I/O error occurs. diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClasses.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClasses.java index 2295ca5c625..b61be1effa0 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClasses.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/InnerClasses.java @@ -42,7 +42,7 @@ public final class InnerClasses extends Attribute implements IterableClassGen class. * * @see com.sun.org.apache.bcel.internal.generic.ClassGen - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparable { @@ -67,26 +68,23 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl public static final byte HEAP = 1; public static final byte FILE = 2; public static final byte ZIP = 3; - private static BCELComparator bcelComparator = new BCELComparator() { + private static BCELComparator bcelComparator = new BCELComparator() { @Override - public boolean equals(final Object o1, final Object o2) { - final JavaClass THIS = (JavaClass) o1; - final JavaClass THAT = (JavaClass) o2; - return Objects.equals(THIS.getClassName(), THAT.getClassName()); + public boolean equals(final JavaClass a, final JavaClass b) { + return a == b || a != null && b != null && Objects.equals(a.getClassName(), b.getClassName()); } @Override - public int hashCode(final Object o) { - final JavaClass THIS = (JavaClass) o; - return THIS.getClassName().hashCode(); + public int hashCode(final JavaClass o) { + return o != null ? Objects.hashCode(o.getClassName()) : 0; } }; /** - * @return Comparison strategy object + * @return Comparison strategy object. */ - public static BCELComparator getComparator() { + public static BCELComparator getComparator() { return bcelComparator; } @@ -100,9 +98,9 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl } /** - * @param comparator Comparison strategy object + * @param comparator Comparison strategy object. */ - public static void setComparator(final BCELComparator comparator) { + public static void setComparator(final BCELComparator comparator) { bcelComparator = comparator; } @@ -128,8 +126,10 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl private boolean isAnonymous; private boolean isNested; + private boolean isRecord; private boolean computedNestedTypeStatus; + private boolean computedRecord; /** * In cases where we go ahead and create something, use the default SyntheticRepository, because we don't know any @@ -177,17 +177,15 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl public JavaClass(final int classNameIndex, final int superclassNameIndex, final String fileName, final int major, final int minor, final int accessFlags, final ConstantPool constantPool, int[] interfaces, Field[] fields, Method[] methods, Attribute[] attributes, final byte source) { super(accessFlags); - if (interfaces == null) { - interfaces = Const.EMPTY_INT_ARRAY; - } + interfaces = Utils.createEmptyArrayIfNull(interfaces); if (attributes == null) { attributes = Attribute.EMPTY_ARRAY; } if (fields == null) { - fields = Field.EMPTY_FIELD_ARRAY; + fields = Field.EMPTY_ARRAY; } if (methods == null) { - methods = Method.EMPTY_METHOD_ARRAY; + methods = Method.EMPTY_ARRAY; } this.classNameIndex = classNameIndex; this.superclassNameIndex = superclassNameIndex; @@ -254,6 +252,19 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl return getClassName().compareTo(obj.getClassName()); } + private void computeIsRecord() { + if (computedRecord) { + return; + } + for (final Attribute attribute : this.attributes) { + if (attribute instanceof Record) { + isRecord = true; + break; + } + } + this.computedRecord = true; + } + private void computeNestedTypeStatus() { if (computedNestedTypeStatus) { return; @@ -384,11 +395,51 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl */ @Override public boolean equals(final Object obj) { - return bcelComparator.equals(this, obj); + return obj instanceof JavaClass && bcelComparator.equals(this, (JavaClass) obj); } /** - * Get all interfaces implemented by this JavaClass (transitively). + * Finds a visible field by name and type in this class and its super classes. + * @param fieldName the field name to find + * @param fieldType the field type to find + * @return field matching given name and type, null if field is not found or not accessible from this class. + * @throws ClassNotFoundException + * @since 6.8.0 + */ + public Field findField(final String fieldName, final Type fieldType) throws ClassNotFoundException { + for (final Field field : fields) { + if (field.getName().equals(fieldName)) { + final Type fType = Type.getType(field.getSignature()); + /* + * TODO: Check if assignment compatibility is sufficient. What does Sun do? + */ + if (fType.equals(fieldType)) { + return field; + } + } + } + + final JavaClass superclass = getSuperClass(); + if (superclass != null && !"java.lang.Object".equals(superclass.getClassName())) { + final Field f = superclass.findField(fieldName, fieldType); + if (f != null && (f.isPublic() || f.isProtected() || !f.isPrivate() && packageName.equals(superclass.getPackageName()))) { + return f; + } + } + final JavaClass[] implementedInterfaces = getInterfaces(); + if (implementedInterfaces != null) { + for (final JavaClass implementedInterface : implementedInterfaces) { + final Field f = implementedInterface.findField(fieldName, fieldType); + if (f != null) { + return f; + } + } + } + return null; + } + + /** + * Gets all interfaces implemented by this JavaClass (transitively). * * @throws ClassNotFoundException if any of the class's superclasses or interfaces can't be found. */ @@ -409,7 +460,7 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl queue.enqueue(iface); } } - return allInterfaces.toArray(JavaClass.EMPTY_ARRAY); + return allInterfaces.toArray(EMPTY_ARRAY); } /** @@ -424,6 +475,22 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl return annotations; } + /** + * Gets attribute for given tag. + * @return Attribute for given tag, null if not found. + * Refer to {@link com.sun.org.apache.bcel.internal.Const#ATTR_UNKNOWN} constants named ATTR_* for possible values. + * @since 6.10.0 + */ + @SuppressWarnings("unchecked") + public final T getAttribute(final byte tag) { + for (final Attribute attribute : getAttributes()) { + if (attribute.getTag() == tag) { + return (T) attribute; + } + } + return null; + } + /** * @return Attributes of the class. */ @@ -495,7 +562,7 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl } /** - * Get interfaces directly implemented by this JavaClass. + * Gets interfaces directly implemented by this JavaClass. * * @throws ClassNotFoundException if any of the class's interfaces can't be found. */ @@ -587,7 +654,7 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl } /** - * @return the superclass for this JavaClass object, or null if this is java.lang.Object + * @return the superclass for this JavaClass object, or null if this is {@link Object} * @throws ClassNotFoundException if the superclass can't be found */ public JavaClass getSuperClass() throws ClassNotFoundException { @@ -607,12 +674,12 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl for (clazz = clazz.getSuperClass(); clazz != null; clazz = clazz.getSuperClass()) { allSuperClasses.add(clazz); } - return allSuperClasses.toArray(JavaClass.EMPTY_ARRAY); + return allSuperClasses.toArray(EMPTY_ARRAY); } /** - * returns the super class name of this class. In the case that this class is java.lang.Object, it will return itself - * (java.lang.Object). This is probably incorrect but isn't fixed at this time to not break existing clients. + * returns the super class name of this class. In the case that this class is {@link Object}, it will return itself + * ({@link Object}). This is probably incorrect but isn't fixed at this time to not break existing clients. * * @return Superclass name. */ @@ -628,7 +695,7 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl } /** - * Return value as defined by given BCELComparator strategy. By default return the hashcode of the class name. + * Return value as defined by given BCELComparator strategy. By default return the hash code of the class name. * * @see Object#hashCode() */ @@ -645,7 +712,7 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl if (!inter.isInterface()) { throw new IllegalArgumentException(inter.getClassName() + " is no interface"); } - if (this.equals(inter)) { + if (equals(inter)) { return true; } final JavaClass[] superInterfaces = getAllInterfaces(); @@ -664,7 +731,7 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl * @throws ClassNotFoundException if superclasses or superinterfaces of this object can't be found */ public final boolean instanceOf(final JavaClass superclass) throws ClassNotFoundException { - if (this.equals(superclass)) { + if (equals(superclass)) { return true; } for (final JavaClass clazz : getSuperClasses()) { @@ -698,6 +765,17 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl return this.isNested; } + /** + * Tests whether this class was declared as a record + * + * @return true if a record attribute is present, false otherwise. + * @since 6.9.0 + */ + public boolean isRecord() { + computeIsRecord(); + return this.isRecord; + } + public final boolean isSuper() { return (super.getAccessFlags() & Const.ACC_SUPER) != 0; } @@ -706,7 +784,7 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl * @param attributes . */ public void setAttributes(final Attribute[] attributes) { - this.attributes = attributes; + this.attributes = attributes != null ? attributes : Attribute.EMPTY_ARRAY; } /** @@ -734,11 +812,11 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl * @param fields . */ public void setFields(final Field[] fields) { - this.fields = fields; + this.fields = fields != null ? fields : Field.EMPTY_ARRAY; } /** - * Set File name of class, aka SourceFile attribute value + * Sets File name of class, aka SourceFile attribute value */ public void setFileName(final String fileName) { this.fileName = fileName; @@ -748,14 +826,14 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl * @param interfaceNames . */ public void setInterfaceNames(final String[] interfaceNames) { - this.interfaceNames = interfaceNames; + this.interfaceNames = Utils.createEmptyArrayIfNull(interfaceNames, String[].class); } /** * @param interfaces . */ public void setInterfaces(final int[] interfaces) { - this.interfaces = interfaces; + this.interfaces = Utils.createEmptyArrayIfNull(interfaces); } /** @@ -769,7 +847,7 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl * @param methods . */ public void setMethods(final Method[] methods) { - this.methods = methods; + this.methods = methods != null ? methods : Method.EMPTY_ARRAY; } /** @@ -787,7 +865,7 @@ public class JavaClass extends AccessFlags implements Cloneable, Node, Comparabl } /** - * Set absolute path to file this class was read from. + * Sets absolute path to file this class was read from. */ public void setSourceFileName(final String sourceFileName) { this.sourceFileName = sourceFileName; diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumber.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumber.java index 4380d04bc06..dc41ad065f8 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumber.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumber.java @@ -40,11 +40,11 @@ public final class LineNumber implements Cloneable, Node { /** Program Counter (PC) corresponds to line */ private int startPc; - /** number in source file */ + /** Number in source file */ private int lineNumber; /** - * Construct object from file stream. + * Constructs object from file stream. * * @param file Input stream * @throws IOException if an I/O Exception occurs in readUnsignedShort diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumberTable.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumberTable.java index 6251fc514cc..96541f309bd 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumberTable.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/LineNumberTable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -36,7 +36,7 @@ import jdk.xml.internal.SecuritySupport; * * @see Code * @see LineNumber - * @LastModified: May 2021 + * @LastModified: Sept 2025 */ public final class LineNumberTable extends Attribute implements Iterable { @@ -44,7 +44,7 @@ public final class LineNumberTable extends Attribute implements Iterable + * Note that both objects use the same references (shallow copy). Use copy() for a physical copy. + *

*/ public LineNumberTable(final LineNumberTable c) { this(c.getNameIndex(), c.getLength(), c.getLineNumberTable(), c.getConstantPool()); @@ -190,7 +191,7 @@ public final class LineNumberTable extends Attribute implements Iterable { + private static final LocalVariable[] EMPTY_ARRAY = {}; + private LocalVariable[] localVariableTable; // variables /** - * Construct object from input stream. + * Constructs object from input stream. * * @param nameIndex Index in constant pool * @param length Content length in bytes @@ -68,7 +70,7 @@ public class LocalVariableTable extends Attribute implements Iterable { + private static final LocalVariable[] EMPTY_ARRAY = {}; + private LocalVariable[] localVariableTypeTable; // variables LocalVariableTypeTable(final int nameIdx, final int len, final DataInput input, final ConstantPool cpool) throws IOException { this(nameIdx, len, (LocalVariable[]) null, cpool); - final int localVariableTypeTableLength = input.readUnsignedShort(); localVariableTypeTable = new LocalVariable[localVariableTypeTableLength]; - for (int i = 0; i < localVariableTypeTableLength; i++) { localVariableTypeTable[i] = new LocalVariable(input, cpool); } @@ -97,7 +97,6 @@ public class LocalVariableTypeTable extends Attribute implements Iterable localVariableTypeTable[i].copy()); c.setConstantPool(constantPool); @@ -119,7 +118,6 @@ public class LocalVariableTypeTable extends Attribute implements Iterable bcelComparator = new BCELComparator() { @Override - public boolean equals(final Object o1, final Object o2) { - final Method THIS = (Method) o1; - final Method THAT = (Method) o2; - return Objects.equals(THIS.getName(), THAT.getName()) && Objects.equals(THIS.getSignature(), THAT.getSignature()); + public boolean equals(final Method a, final Method b) { + return a == b || a != null && b != null && Objects.equals(a.getName(), b.getName()) && Objects.equals(a.getSignature(), b.getSignature()); } @Override - public int hashCode(final Object o) { - final Method THIS = (Method) o; - return THIS.getSignature().hashCode() ^ THIS.getName().hashCode(); + public int hashCode(final Method o) { + return o != null ? Objects.hash(o.getSignature(), o.getName()) : 0; } }; /** - * Empty array. + * @return Comparison strategy object. */ - static final Method[] EMPTY_METHOD_ARRAY = {}; - - /** - * @return Comparison strategy object - */ - public static BCELComparator getComparator() { + public static BCELComparator getComparator() { return bcelComparator; } /** - * @param comparator Comparison strategy object + * @param comparator Comparison strategy object. */ - public static void setComparator(final BCELComparator comparator) { + public static void setComparator(final BCELComparator comparator) { bcelComparator = comparator; } - // annotations defined on the parameters of a method + /** Annotations defined on the parameters of a method. */ private ParameterAnnotationEntry[] parameterAnnotationEntries; /** @@ -85,7 +77,7 @@ public final class Method extends FieldOrMethod { } /** - * Construct object from file stream. + * Constructs object from file stream. * * @param file Input stream * @throws IOException if an I/O error occurs. @@ -142,7 +134,7 @@ public final class Method extends FieldOrMethod { */ @Override public boolean equals(final Object obj) { - return bcelComparator.equals(this, obj); + return obj instanceof Method && bcelComparator.equals(this, (Method) obj); } /** @@ -189,7 +181,7 @@ public final class Method extends FieldOrMethod { } /** - * @return LocalVariableTable of code attribute if any, i.e. the call is forwarded to the Code atribute. + * @return LocalVariableTable of code attribute if any, i.e. the call is forwarded to the Code attribute. */ public LocalVariableTable getLocalVariableTable() { final Code code = getCode(); @@ -199,6 +191,19 @@ public final class Method extends FieldOrMethod { return code.getLocalVariableTable(); } + /** + * Gets the local variable type table attribute {@link LocalVariableTypeTable}. + * @return LocalVariableTypeTable of code attribute if any, i.e. the call is forwarded to the Code attribute. + * @since 6.10.0 + */ + public LocalVariableTypeTable getLocalVariableTypeTable() { + final Code code = getCode(); + if (code == null) { + return null; + } + return code.getLocalVariableTypeTable(); + } + /** * @return Annotations on the parameters of a method * @since 6.0 @@ -218,7 +223,7 @@ public final class Method extends FieldOrMethod { } /** - * Return value as defined by given BCELComparator strategy. By default return the hashcode of the method's name XOR + * Return value as defined by given BCELComparator strategy. By default return the hash code of the method's name XOR * signature. * * @see Object#hashCode() diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameter.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameter.java index ffc1a20f80a..865e154d334 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameter.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameter.java @@ -29,6 +29,9 @@ import com.sun.org.apache.bcel.internal.Const; /** * Entry of the parameters table. + *

+ * Implements {@link Node} as of 6.7.0. + *

* * @see The class File Format : * The MethodParameters Attribute @@ -46,7 +49,7 @@ public class MethodParameter implements Cloneable, Node { } /** - * Construct object from input stream. + * Constructs an instance from a DataInput. * * @param input Input stream * @throws IOException if an I/O error occurs. @@ -75,7 +78,7 @@ public class MethodParameter implements Cloneable, Node { } /** - * Dump object to file stream on binary format. + * Dumps object to file stream on binary format. * * @param file Output file stream * @throws IOException if an I/O error occurs. @@ -94,7 +97,10 @@ public class MethodParameter implements Cloneable, Node { } /** - * Returns the name of the parameter. + * Gets the name of the parameter. + * + * @param constantPool The pool to query. + * @return Constant from the given pool. */ public String getParameterName(final ConstantPool constantPool) { if (nameIndex == 0) { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameters.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameters.java index 5b5d1d77f6f..2f5bffd8d3c 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameters.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/MethodParameters.java @@ -42,13 +42,12 @@ public class MethodParameters extends Attribute implements Iterable parameters[i].copy()); c.setConstantPool(constantPool); return c; @@ -96,6 +94,6 @@ public class MethodParameters extends Attribute implements IterableAttribute and represents the list of packages that are exported or opened by the * Module attribute. There may be at most one ModulePackages attribute in a ClassFile structure. * * @see Attribute - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public final class ModulePackages extends Attribute { private int[] packageIndexTable; /** - * Construct object from input stream. + * Constructs object from input stream. * * @param nameIndex Index in constant pool * @param length Content length in bytes @@ -65,7 +66,7 @@ public final class ModulePackages extends Attribute { */ public ModulePackages(final int nameIndex, final int length, final int[] packageIndexTable, final ConstantPool constantPool) { super(Const.ATTR_MODULE_PACKAGES, nameIndex, length, constantPool); - this.packageIndexTable = packageIndexTable != null ? packageIndexTable : Const.EMPTY_INT_ARRAY; + this.packageIndexTable = Utils.createEmptyArrayIfNull(packageIndexTable); Args.requireU2(this.packageIndexTable.length, "packageIndexTable.length"); } @@ -145,7 +146,7 @@ public final class ModulePackages extends Attribute { * @param packageIndexTable the list of package indexes Also redefines number_of_packages according to table length. */ public void setPackageIndexTable(final int[] packageIndexTable) { - this.packageIndexTable = packageIndexTable != null ? packageIndexTable : Const.EMPTY_INT_ARRAY; + this.packageIndexTable = Utils.createEmptyArrayIfNull(packageIndexTable); } /** diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleProvides.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleProvides.java index f6c6058dfbb..490e9cd5d44 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleProvides.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleProvides.java @@ -36,12 +36,20 @@ import com.sun.org.apache.bcel.internal.Const; */ public final class ModuleProvides implements Cloneable, Node { + private static String getImplementationClassNameAtIndex(final ConstantPool constantPool, final int index, final boolean compactClassName) { + final String className = constantPool.getConstantString(index, Const.CONSTANT_Class); + if (compactClassName) { + return Utility.compactClassName(className, false); + } + return className; + } private final int providesIndex; // points to CONSTANT_Class_info private final int providesWithCount; + private final int[] providesWithIndex; // points to CONSTANT_Class_info /** - * Construct object from file stream. + * Constructs object from file stream. * * @param file Input stream * @throws IOException if an I/O Exception occurs in readUnsignedShort @@ -66,8 +74,6 @@ public final class ModuleProvides implements Cloneable, Node { v.visitModuleProvides(this); } - // TODO add more getters and setters? - /** * @return deep copy of this object */ @@ -94,6 +100,31 @@ public final class ModuleProvides implements Cloneable, Node { } } + /** + * Gets the array of implementation class names for this ModuleProvides. + * @param constantPool Array of constants usually obtained from the ClassFile object + * @param compactClassName false for original constant pool value, true to replace '/' with '.' + * @return array of implementation class names + * @since 6.10.0 + */ + public String[] getImplementationClassNames(final ConstantPool constantPool, final boolean compactClassName) { + final String[] implementationClassNames = new String[providesWithCount]; + for (int i = 0; i < providesWithCount; i++) { + implementationClassNames[i] = getImplementationClassNameAtIndex(constantPool, providesWithIndex[i], compactClassName); + } + return implementationClassNames; + } + + /** + * Gets the interface name for this ModuleProvides. + * @param constantPool Array of constants usually obtained from the ClassFile object + * @return interface name + * @since 6.10.0 + */ + public String getInterfaceName(final ConstantPool constantPool) { + return constantPool.constantToString(providesIndex, Const.CONSTANT_Class); + } + /** * @return String representation */ @@ -107,12 +138,12 @@ public final class ModuleProvides implements Cloneable, Node { */ public String toString(final ConstantPool constantPool) { final StringBuilder buf = new StringBuilder(); - final String interfaceName = constantPool.constantToString(providesIndex, Const.CONSTANT_Class); - buf.append(Utility.compactClassName(interfaceName, false)); + final String interfaceName = getInterfaceName(constantPool); + buf.append(interfaceName); buf.append(", with(").append(providesWithCount).append("):\n"); for (final int index : providesWithIndex) { - final String className = constantPool.getConstantString(index, Const.CONSTANT_Class); - buf.append(" ").append(Utility.compactClassName(className, false)).append("\n"); + final String className = getImplementationClassNameAtIndex(constantPool, index, true); + buf.append(" ").append(className).append("\n"); } return buf.substring(0, buf.length() - 1); // remove the last newline } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleRequires.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleRequires.java index c9c26c20649..3149a18290b 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleRequires.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ModuleRequires.java @@ -41,7 +41,7 @@ public final class ModuleRequires implements Cloneable, Node { private final int requiresVersionIndex; // either 0 or points to CONSTANT_Utf8_info /** - * Construct object from file stream. + * Constructs object from file stream. * * @param file Input stream * @throws IOException if an I/O Exception occurs in readUnsignedShort @@ -63,8 +63,6 @@ public final class ModuleRequires implements Cloneable, Node { v.visitModuleRequires(this); } - // TODO add more getters and setters? - /** * @return deep copy of this object */ @@ -89,6 +87,35 @@ public final class ModuleRequires implements Cloneable, Node { file.writeShort(requiresVersionIndex); } + /** + * Gets the module name from the constant pool. + * @param constantPool Array of constants usually obtained from the ClassFile object + * @return module name + * @since 6.10.0 + */ + public String getModuleName(final ConstantPool constantPool) { + return constantPool.constantToString(requiresIndex, Const.CONSTANT_Module); + } + + /** + * Gets the flags for this ModuleRequires. + * @return the requiresFlags + * @since 6.10.0 + */ + public int getRequiresFlags() { + return requiresFlags; + } + + /** + * Gets the required version from the constant pool. + * @param constantPool Array of constants usually obtained from the ClassFile object + * @return required version, "0" if version index is 0. + * @since 6.10.0 + */ + public String getVersion(final ConstantPool constantPool) { + return requiresVersionIndex == 0 ? "0" : constantPool.getConstantString(requiresVersionIndex, Const.CONSTANT_Utf8); + } + /** * @return String representation */ @@ -102,10 +129,10 @@ public final class ModuleRequires implements Cloneable, Node { */ public String toString(final ConstantPool constantPool) { final StringBuilder buf = new StringBuilder(); - final String moduleName = constantPool.constantToString(requiresIndex, Const.CONSTANT_Module); - buf.append(Utility.compactClassName(moduleName, false)); + final String moduleName = getModuleName(constantPool); + buf.append(moduleName); buf.append(", ").append(String.format("%04x", requiresFlags)); - final String version = requiresVersionIndex == 0 ? "0" : constantPool.getConstantString(requiresVersionIndex, Const.CONSTANT_Utf8); + final String version = getVersion(constantPool); buf.append(", ").append(version); return buf.toString(); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/NestMembers.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/NestMembers.java index 05d982ca6e8..261f57d98a8 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/NestMembers.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/NestMembers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -27,6 +27,7 @@ import java.util.Arrays; import com.sun.org.apache.bcel.internal.Const; import com.sun.org.apache.bcel.internal.util.Args; +import jdk.xml.internal.Utils; /** * This class is derived from Attribute and records the classes and interfaces that are authorized to claim @@ -34,14 +35,14 @@ import com.sun.org.apache.bcel.internal.util.Args; * ClassFile structure. * * @see Attribute - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public final class NestMembers extends Attribute { private int[] classes; /** - * Construct object from input stream. + * Constructs object from input stream. * * @param nameIndex Index in constant pool * @param length Content length in bytes @@ -66,7 +67,7 @@ public final class NestMembers extends Attribute { */ public NestMembers(final int nameIndex, final int length, final int[] classes, final ConstantPool constantPool) { super(Const.ATTR_NEST_MEMBERS, nameIndex, length, constantPool); - this.classes = classes != null ? classes : Const.EMPTY_INT_ARRAY; + this.classes = Utils.createEmptyArrayIfNull(classes); Args.requireU2(this.classes.length, "classes.length"); } @@ -146,7 +147,7 @@ public final class NestMembers extends Attribute { * @param classes the list of class indexes Also redefines number_of_classes according to table length. */ public void setClasses(final int[] classes) { - this.classes = classes != null ? classes : Const.EMPTY_INT_ARRAY; + this.classes = Utils.createEmptyArrayIfNull(classes); } /** diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Node.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Node.java index c0395732d79..792ef31cb72 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Node.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Node.java @@ -26,5 +26,5 @@ package com.sun.org.apache.bcel.internal.classfile; */ public interface Node { - void accept(Visitor obj); + void accept(Visitor visitor); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/PMGClass.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/PMGClass.java index 9b1dd4c7b41..b7b5e1f1d99 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/PMGClass.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/PMGClass.java @@ -38,7 +38,7 @@ public final class PMGClass extends Attribute { private int pmgIndex; /** - * Construct object from input stream. + * Constructs object from input stream. * * @param nameIndex Index in constant pool to CONSTANT_Utf8 * @param length Content length in bytes diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotationEntry.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotationEntry.java index a3070fa7e0c..6ebe60c8049 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotationEntry.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotationEntry.java @@ -37,22 +37,28 @@ public class ParameterAnnotationEntry implements Node { static final ParameterAnnotationEntry[] EMPTY_ARRAY = {}; - public static ParameterAnnotationEntry[] createParameterAnnotationEntries(final Attribute[] attrs) { + public static ParameterAnnotationEntry[] createParameterAnnotationEntries(final Attribute[] attributes) { + if (attributes == null) { + return EMPTY_ARRAY; + } // Find attributes that contain parameter annotation data - final List accumulatedAnnotations = new ArrayList<>(attrs.length); - for (final Attribute attribute : attrs) { + final List accumulatedAnnotations = new ArrayList<>(attributes.length); + for (final Attribute attribute : attributes) { if (attribute instanceof ParameterAnnotations) { final ParameterAnnotations runtimeAnnotations = (ParameterAnnotations) attribute; - Collections.addAll(accumulatedAnnotations, runtimeAnnotations.getParameterAnnotationEntries()); + final ParameterAnnotationEntry[] parameterAnnotationEntries = runtimeAnnotations.getParameterAnnotationEntries(); + if (parameterAnnotationEntries != null) { + Collections.addAll(accumulatedAnnotations, parameterAnnotationEntries); + } } } - return accumulatedAnnotations.toArray(ParameterAnnotationEntry.EMPTY_ARRAY); + return accumulatedAnnotations.toArray(EMPTY_ARRAY); } private final AnnotationEntry[] annotationTable; /** - * Construct object from input stream. + * Constructs object from input stream. * * @param input Input stream * @throws IOException if an I/O error occurs. diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotations.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotations.java index 4817793120f..1e056b5d4f8 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotations.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/ParameterAnnotations.java @@ -34,10 +34,14 @@ import java.util.stream.Stream; */ public abstract class ParameterAnnotations extends Attribute implements Iterable { + private static final ParameterAnnotationEntry[] EMPTY_ARRAY = {}; + /** Table of parameter annotations */ private ParameterAnnotationEntry[] parameterAnnotationTable; /** + * Constructs a new instance. + * * @param parameterAnnotationType the subclass type of the parameter annotation * @param nameIndex Index pointing to the name Code * @param length Content length in bytes @@ -55,6 +59,8 @@ public abstract class ParameterAnnotations extends Attribute implements Iterable } /** + * Constructs a new instance. + * * @param parameterAnnotationType the subclass type of the parameter annotation * @param nameIndex Index pointing to the name Code * @param length Content length in bytes @@ -120,6 +126,6 @@ public abstract class ParameterAnnotations extends Attribute implements Iterable * @param parameterAnnotationTable the entries to set in this parameter annotation */ public final void setParameterAnnotationTable(final ParameterAnnotationEntry[] parameterAnnotationTable) { - this.parameterAnnotationTable = parameterAnnotationTable; + this.parameterAnnotationTable = parameterAnnotationTable != null ? parameterAnnotationTable : EMPTY_ARRAY; } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Record.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Record.java new file mode 100644 index 00000000000..f59cfa37ca4 --- /dev/null +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Record.java @@ -0,0 +1,153 @@ +/* + * reserved comment block + * DO NOT REMOVE OR ALTER! + */ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.sun.org.apache.bcel.internal.classfile; + +import java.io.DataInput; +import java.io.DataOutputStream; +import java.io.IOException; + +import com.sun.org.apache.bcel.internal.Const; +import com.sun.org.apache.bcel.internal.util.Args; + +/** + * Extends {@link Attribute} and records the classes and + * interfaces that are authorized to claim membership in the nest hosted by the + * current class or interface. There may be at most one Record attribute in a + * ClassFile structure. + * + * @see Attribute + * @since 6.9.0 + */ +public final class Record extends Attribute { + + private static final RecordComponentInfo[] EMPTY_RCI_ARRAY = {}; + + private static RecordComponentInfo[] readComponents(final DataInput input, final ConstantPool constantPool) + throws IOException { + final int classCount = input.readUnsignedShort(); + final RecordComponentInfo[] components = new RecordComponentInfo[classCount]; + for (int i = 0; i < classCount; i++) { + components[i] = new RecordComponentInfo(input, constantPool); + } + return components; + } + + private RecordComponentInfo[] components; + + /** + * Constructs object from input stream. + * + * @param nameIndex Index in constant pool + * @param length Content length in bytes + * @param input Input stream + * @param constantPool Array of constants + * @throws IOException if an I/O error occurs. + */ + Record(final int nameIndex, final int length, final DataInput input, final ConstantPool constantPool) + throws IOException { + this(nameIndex, length, readComponents(input, constantPool), constantPool); + } + + /** + * Constructs a new instance using components. + * + * @param nameIndex Index in constant pool + * @param length Content length in bytes + * @param classes Array of Record Component Info elements + * @param constantPool Array of constants + */ + public Record(final int nameIndex, final int length, final RecordComponentInfo[] classes, + final ConstantPool constantPool) { + super(Const.ATTR_RECORD, nameIndex, length, constantPool); + this.components = classes != null ? classes : EMPTY_RCI_ARRAY; + Args.requireU2(this.components.length, "attributes.length"); + } + + /** + * Called by objects that are traversing the nodes of the tree implicitly + * defined by the contents of a Java class. For example, the hierarchy of methods, + * fields, attributes, etc. spawns a tree of objects. + * + * @param v Visitor object + */ + @Override + public void accept(final Visitor v) { + v.visitRecord(this); + } + + /** + * Copies this instance and its components. + * + * @return a deep copy of this instance and its components. + */ + @Override + public Attribute copy(final ConstantPool constantPool) { + final Record c = (Record) clone(); + if (components.length > 0) { + c.components = components.clone(); + } + c.setConstantPool(constantPool); + return c; + } + + /** + * Dumps this instance into a file stream in binary format. + * + * @param file output stream. + * @throws IOException if an I/O error occurs. + */ + @Override + public void dump(final DataOutputStream file) throws IOException { + super.dump(file); + file.writeShort(components.length); + for (final RecordComponentInfo component : components) { + component.dump(file); + } + } + + /** + * Gets all the record components. + * + * @return array of Record Component Info elements. + */ + public RecordComponentInfo[] getComponents() { + return components; + } + + /** + * Converts this instance to a String suitable for debugging. + * + * @return String a String suitable for debugging. + */ + @Override + public String toString() { + final StringBuilder buf = new StringBuilder(); + buf.append("Record("); + buf.append(components.length); + buf.append("):\n"); + for (final RecordComponentInfo component : components) { + buf.append(" ").append(component.toString()).append("\n"); + } + return buf.substring(0, buf.length() - 1); // remove the last newline + } + +} diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RecordComponentInfo.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RecordComponentInfo.java new file mode 100644 index 00000000000..3679647d409 --- /dev/null +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RecordComponentInfo.java @@ -0,0 +1,139 @@ +/* + * reserved comment block + * DO NOT REMOVE OR ALTER! + */ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.sun.org.apache.bcel.internal.classfile; + +import java.io.DataInput; +import java.io.DataOutputStream; +import java.io.IOException; + +import com.sun.org.apache.bcel.internal.Const; + +/** + * Record component info from a record. Instances from this class maps + * every component from a given record. + * + * @see + * The Java Virtual Machine Specification, Java SE 14 Edition, Records (preview) + * @since 6.9.0 + */ +public class RecordComponentInfo implements Node { + + private final int index; + private final int descriptorIndex; + private final Attribute[] attributes; + private final ConstantPool constantPool; + + /** + * Constructs a new instance from an input stream. + * + * @param input Input stream + * @param constantPool Array of constants + * @throws IOException if an I/O error occurs. + */ + public RecordComponentInfo(final DataInput input, final ConstantPool constantPool) throws IOException { + this.index = input.readUnsignedShort(); + this.descriptorIndex = input.readUnsignedShort(); + final int attributesCount = input.readUnsignedShort(); + this.attributes = new Attribute[attributesCount]; + for (int j = 0; j < attributesCount; j++) { + attributes[j] = Attribute.readAttribute(input, constantPool); + } + this.constantPool = constantPool; + } + + @Override + public void accept(final Visitor v) { + v.visitRecordComponent(this); + } + + /** + * Dumps contents into a file stream in binary format. + * + * @param file Output file stream + * @throws IOException if an I/O error occurs. + */ + public void dump(final DataOutputStream file) throws IOException { + file.writeShort(index); + file.writeShort(descriptorIndex); + file.writeShort(attributes.length); + for (final Attribute attribute : attributes) { + attribute.dump(file); + } + } + + /** + * Gets all attributes. + * + * @return all attributes. + */ + public Attribute[] getAttributes() { + return attributes; + } + + /** + * Gets the constant pool. + * + * @return Constant pool. + */ + public ConstantPool getConstantPool() { + return constantPool; + } + + /** + * Gets the description index. + * + * @return index in constant pool of this record component descriptor. + */ + public int getDescriptorIndex() { + return descriptorIndex; + } + + /** + * Gets the name index. + * + * @return index in constant pool of this record component name. + */ + public int getIndex() { + return index; + } + + /** + * Converts this instance to a String suitable for debugging. + * + * @return a String suitable for debugging. + */ + @Override + public String toString() { + final StringBuilder buf = new StringBuilder(); + buf.append("RecordComponentInfo("); + buf.append(constantPool.getConstantString(index, Const.CONSTANT_Utf8)); + buf.append(","); + buf.append(constantPool.getConstantString(descriptorIndex, Const.CONSTANT_Utf8)); + buf.append(","); + buf.append(attributes.length); + buf.append("):\n"); + for (final Attribute attribute : attributes) { + buf.append(" ").append(attribute.toString()).append("\n"); + } + return buf.substring(0, buf.length() - 1); // remove the last newline + } + +} diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleAnnotations.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleAnnotations.java index 7afb8719559..7a7c539f15a 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleAnnotations.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleAnnotations.java @@ -28,13 +28,15 @@ import java.io.IOException; import com.sun.org.apache.bcel.internal.Const; /** - * represents an annotation that is represented in the class file but is not provided to the JVM. + * An annotation that is represented in the class file but is not provided to the JVM. * * @since 6.0 */ public class RuntimeInvisibleAnnotations extends Annotations { /** + * Constructs a new instance. + * * @param nameIndex Index pointing to the name Code * @param length Content length in bytes * @param input Input stream @@ -46,7 +48,9 @@ public class RuntimeInvisibleAnnotations extends Annotations { } /** - * @return deep copy of this attribute + * Creates a deep copy of this attribute. + * + * @return deep copy of this attribute. */ @Override public Attribute copy(final ConstantPool constantPool) { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleParameterAnnotations.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleParameterAnnotations.java index e4c3276f968..3d50ce16d40 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleParameterAnnotations.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeInvisibleParameterAnnotations.java @@ -34,6 +34,8 @@ import com.sun.org.apache.bcel.internal.Const; public class RuntimeInvisibleParameterAnnotations extends ParameterAnnotations { /** + * Constructs a new instance. + * * @param nameIndex Index pointing to the name Code * @param length Content length in bytes * @param input Input stream diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleAnnotations.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleAnnotations.java index c91c77387b9..4bf8e6f7197 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleAnnotations.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleAnnotations.java @@ -28,13 +28,15 @@ import java.io.IOException; import com.sun.org.apache.bcel.internal.Const; /** - * represents an annotation that is represented in the class file and is provided to the JVM. + * An annotation that is represented in the class file and is provided to the JVM. * * @since 6.0 */ public class RuntimeVisibleAnnotations extends Annotations { /** + * Constructs a new instance. + * * @param nameIndex Index pointing to the name Code * @param length Content length in bytes * @param input Input stream @@ -46,7 +48,9 @@ public class RuntimeVisibleAnnotations extends Annotations { } /** - * @return deep copy of this attribute + * Creates a deep copy of this attribute. + * + * @return deep copy of this attribute. */ @Override public Attribute copy(final ConstantPool constantPool) { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleParameterAnnotations.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleParameterAnnotations.java index 7e5d7eaaca3..ab5355235f6 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleParameterAnnotations.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/RuntimeVisibleParameterAnnotations.java @@ -34,6 +34,8 @@ import com.sun.org.apache.bcel.internal.Const; public class RuntimeVisibleParameterAnnotations extends ParameterAnnotations { /** + * Constructs a new instance. + * * @param nameIndex Index pointing to the name Code * @param length Content length in bytes * @param input Input stream diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Signature.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Signature.java index 4f5d3a341b3..2161bbcb6ec 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Signature.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Signature.java @@ -110,7 +110,7 @@ public final class Signature extends Attribute { if ((ch = in.read()) == -1) { throw new IllegalArgumentException("Illegal signature: " + in.getData() + " no ident, reaching EOF"); } - // System.out.println("return from ident:" + (char)ch); + // System.out.println("return from ident:" + (char) ch); if (!identStart(ch)) { final StringBuilder buf2 = new StringBuilder(); int count = 1; @@ -128,7 +128,7 @@ public final class Signature extends Attribute { buf.append(buf2); ch = in.read(); in.unread(); - // System.out.println("so far:" + buf2 + ":next:" +(char)ch); + // System.out.println("so far:" + buf2 + ":next:" +(char) ch); } else { for (int i = 0; i < count; i++) { in.unread(); @@ -141,10 +141,10 @@ public final class Signature extends Attribute { do { buf2.append((char) ch); ch = in.read(); - // System.out.println("within ident:"+ (char)ch); + // System.out.println("within ident:"+ (char) ch); } while (ch != -1 && (Character.isJavaIdentifierPart((char) ch) || ch == '/')); buf.append(Utility.pathToPackage(buf2.toString())); - // System.out.println("regular return ident:"+ (char)ch + ":" + buf2); + // System.out.println("regular return ident:"+ (char) ch + ":" + buf2); if (ch != -1) { in.unread(); } @@ -160,7 +160,7 @@ public final class Signature extends Attribute { private int signatureIndex; /** - * Construct object from file stream. + * Constructs object from file stream. * * @param nameIndex Index in constant pool to CONSTANT_Utf8 * @param length Content length in bytes diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SimpleElementValue.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SimpleElementValue.java index 5e4e98d94df..e3e1cf40031 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SimpleElementValue.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SimpleElementValue.java @@ -54,7 +54,7 @@ public class SimpleElementValue extends ElementValue { dos.writeShort(getIndex()); break; default: - throw new ClassFormatException("SimpleElementValue doesnt know how to write out type " + type); + throw new ClassFormatException("SimpleElementValue doesn't know how to write out type " + type); } } @@ -67,7 +67,7 @@ public class SimpleElementValue extends ElementValue { public boolean getValueBoolean() { if (super.getType() != PRIMITIVE_BOOLEAN) { - throw new IllegalStateException("Dont call getValueBoolean() on a non BOOLEAN ElementValue"); + throw new IllegalStateException("Don't call getValueBoolean() on a non BOOLEAN ElementValue"); } final ConstantInteger bo = (ConstantInteger) super.getConstantPool().getConstant(getIndex()); return bo.getBytes() != 0; @@ -75,21 +75,21 @@ public class SimpleElementValue extends ElementValue { public byte getValueByte() { if (super.getType() != PRIMITIVE_BYTE) { - throw new IllegalStateException("Dont call getValueByte() on a non BYTE ElementValue"); + throw new IllegalStateException("Don't call getValueByte() on a non BYTE ElementValue"); } return (byte) super.getConstantPool().getConstantInteger(getIndex()).getBytes(); } public char getValueChar() { if (super.getType() != PRIMITIVE_CHAR) { - throw new IllegalStateException("Dont call getValueChar() on a non CHAR ElementValue"); + throw new IllegalStateException("Don't call getValueChar() on a non CHAR ElementValue"); } return (char) super.getConstantPool().getConstantInteger(getIndex()).getBytes(); } public double getValueDouble() { if (super.getType() != PRIMITIVE_DOUBLE) { - throw new IllegalStateException("Dont call getValueDouble() on a non DOUBLE ElementValue"); + throw new IllegalStateException("Don't call getValueDouble() on a non DOUBLE ElementValue"); } final ConstantDouble d = (ConstantDouble) super.getConstantPool().getConstant(getIndex()); return d.getBytes(); @@ -97,7 +97,7 @@ public class SimpleElementValue extends ElementValue { public float getValueFloat() { if (super.getType() != PRIMITIVE_FLOAT) { - throw new IllegalStateException("Dont call getValueFloat() on a non FLOAT ElementValue"); + throw new IllegalStateException("Don't call getValueFloat() on a non FLOAT ElementValue"); } final ConstantFloat f = (ConstantFloat) super.getConstantPool().getConstant(getIndex()); return f.getBytes(); @@ -105,14 +105,14 @@ public class SimpleElementValue extends ElementValue { public int getValueInt() { if (super.getType() != PRIMITIVE_INT) { - throw new IllegalStateException("Dont call getValueInt() on a non INT ElementValue"); + throw new IllegalStateException("Don't call getValueInt() on a non INT ElementValue"); } return super.getConstantPool().getConstantInteger(getIndex()).getBytes(); } public long getValueLong() { if (super.getType() != PRIMITIVE_LONG) { - throw new IllegalStateException("Dont call getValueLong() on a non LONG ElementValue"); + throw new IllegalStateException("Don't call getValueLong() on a non LONG ElementValue"); } final ConstantLong j = (ConstantLong) super.getConstantPool().getConstant(getIndex()); return j.getBytes(); @@ -120,7 +120,7 @@ public class SimpleElementValue extends ElementValue { public short getValueShort() { if (super.getType() != PRIMITIVE_SHORT) { - throw new IllegalStateException("Dont call getValueShort() on a non SHORT ElementValue"); + throw new IllegalStateException("Don't call getValueShort() on a non SHORT ElementValue"); } final ConstantInteger s = (ConstantInteger) super.getConstantPool().getConstant(getIndex()); return (short) s.getBytes(); @@ -128,7 +128,7 @@ public class SimpleElementValue extends ElementValue { public String getValueString() { if (super.getType() != STRING) { - throw new IllegalStateException("Dont call getValueString() on a non STRING ElementValue"); + throw new IllegalStateException("Don't call getValueString() on a non STRING ElementValue"); } return super.getConstantPool().getConstantUtf8(getIndex()).getBytes(); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SourceFile.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SourceFile.java index e9ceed21957..bfa9cbf8fcb 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SourceFile.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/SourceFile.java @@ -40,7 +40,7 @@ public final class SourceFile extends Attribute { private int sourceFileIndex; /** - * Construct object from input stream. + * Constructs object from input stream. * * @param nameIndex Index in constant pool to CONSTANT_Utf8 * @param length Content length in bytes diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMap.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMap.java index 1f8ce5ea410..317638e6b2d 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMap.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -30,8 +30,8 @@ import com.sun.org.apache.bcel.internal.util.Args; /** * This class represents a stack map attribute used for preverification of Java classes for the - * Java 2 Micro Edition (J2ME). This attribute is used by the - * KVM and contained within the Code attribute of a method. See CLDC + * Java 2 Micro Edition (J2ME). This attribute is used by the + * KVM and contained within the Code attribute of a method. See CLDC * specification 5.3.1.2 * *
@@ -46,14 +46,14 @@ import com.sun.org.apache.bcel.internal.util.Args;
  * @see Code
  * @see StackMapEntry
  * @see StackMapType
- * @LastModified: Oct 2020
+ * @LastModified: Sept 2025
  */
 public final class StackMap extends Attribute {
 
     private StackMapEntry[] table; // Table of stack map entries
 
     /**
-     * Construct object from input stream.
+     * Constructs object from input stream.
      *
      * @param nameIndex Index of name
      * @param length Content length in bytes
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapEntry.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapEntry.java
index 110e30392ab..015083dd066 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapEntry.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapEntry.java
@@ -59,7 +59,7 @@ public final class StackMapEntry implements Node, Cloneable {
     private ConstantPool constantPool;
 
     /**
-     * Construct object from input stream.
+     * Constructs object from input stream.
      *
      * @param dataInput Input stream
      * @throws IOException if an I/O error occurs.
@@ -75,9 +75,7 @@ public final class StackMapEntry implements Node, Cloneable {
         } else if (frameType == Const.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) {
             byteCodeOffset = dataInput.readUnsignedShort();
             typesOfStackItems = new StackMapType[] { new StackMapType(dataInput, constantPool) };
-        } else if (frameType >= Const.CHOP_FRAME && frameType <= Const.CHOP_FRAME_MAX) {
-            byteCodeOffset = dataInput.readUnsignedShort();
-        } else if (frameType == Const.SAME_FRAME_EXTENDED) {
+        } else if (frameType >= Const.CHOP_FRAME && frameType <= Const.CHOP_FRAME_MAX || frameType == Const.SAME_FRAME_EXTENDED) {
             byteCodeOffset = dataInput.readUnsignedShort();
         } else if (frameType >= Const.APPEND_FRAME && frameType <= Const.APPEND_FRAME_MAX) {
             byteCodeOffset = dataInput.readUnsignedShort();
@@ -167,7 +165,7 @@ public final class StackMapEntry implements Node, Cloneable {
         try {
             e = (StackMapEntry) clone();
         } catch (final CloneNotSupportedException ex) {
-            throw new Error("Clone Not Supported");
+            throw new UnsupportedOperationException("Clone Not Supported", ex);
         }
 
         e.typesOfLocals = new StackMapType[typesOfLocals.length];
@@ -190,9 +188,7 @@ public final class StackMapEntry implements Node, Cloneable {
         } else if (frameType == Const.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) {
             file.writeShort(byteCodeOffset);
             typesOfStackItems[0].dump(file);
-        } else if (frameType >= Const.CHOP_FRAME && frameType <= Const.CHOP_FRAME_MAX) {
-            file.writeShort(byteCodeOffset);
-        } else if (frameType == Const.SAME_FRAME_EXTENDED) {
+        } else if (frameType >= Const.CHOP_FRAME && frameType <= Const.CHOP_FRAME_MAX || frameType == Const.SAME_FRAME_EXTENDED) {
             file.writeShort(byteCodeOffset);
         } else if (frameType >= Const.APPEND_FRAME && frameType <= Const.APPEND_FRAME_MAX) {
             file.writeShort(byteCodeOffset);
@@ -232,7 +228,6 @@ public final class StackMapEntry implements Node, Cloneable {
 
     /**
      * Calculate stack map entry size
-     *
      */
     int getMapEntrySize() {
         if (frameType >= Const.SAME_FRAME && frameType <= Const.SAME_FRAME_MAX) {
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapType.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapType.java
index 4575b31dfce..b93066d53b7 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapType.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/StackMapType.java
@@ -34,9 +34,9 @@ import com.sun.org.apache.bcel.internal.Const;
  * @see StackMap
  * @see Const
  */
-public final class StackMapType implements Cloneable {
+public final class StackMapType implements Node, Cloneable {
 
-    public static final StackMapType[] EMPTY_ARRAY = {}; // must be public because BCELifier code generator writes calls to it
+    public static final StackMapType[] EMPTY_ARRAY = {}; // BCELifier code generator writes calls to constructor translating null to EMPTY_ARRAY
 
     private byte type;
     private int index = -1; // Index to CONSTANT_Class or offset
@@ -53,7 +53,7 @@ public final class StackMapType implements Cloneable {
     }
 
     /**
-     * Construct object from file stream.
+     * Constructs object from file stream.
      *
      * @param file Input stream
      * @throws IOException if an I/O error occurs.
@@ -66,6 +66,18 @@ public final class StackMapType implements Cloneable {
         this.constantPool = constantPool;
     }
 
+    /**
+     * Called by objects that are traversing the nodes of the tree implicitly defined by the contents of a Java class.
+     * I.e., the hierarchy of methods, fields, attributes, etc. spawns a tree of objects.
+     *
+     * @param v Visitor object
+     * @since 6.8.0
+     */
+    @Override
+    public void accept(final Visitor v) {
+        v.visitStackMapType(this);
+    }
+
     private byte checkType(final byte type) {
         if (type < Const.ITEM_Bogus || type > Const.ITEM_NewObject) {
             throw new ClassFormatException("Illegal type for StackMapType: " + type);
@@ -98,6 +110,15 @@ public final class StackMapType implements Cloneable {
         }
     }
 
+    /**
+     * Gets the class name of this StackMapType from the constant pool at index position.
+     * @return the fully qualified name of the class for this StackMapType.
+     * @since 6.8.0
+     */
+    public String getClassName() {
+        return constantPool.constantToString(index, Const.CONSTANT_Class);
+    }
+
     /**
      * @return Constant pool used by this object.
      */
@@ -129,7 +150,7 @@ public final class StackMapType implements Cloneable {
             if (index < 0) {
                 return ", class=";
             }
-            return ", class=" + constantPool.constantToString(index, Const.CONSTANT_Class);
+            return ", class=" + getClassName();
         }
         if (type == Const.ITEM_NewObject) {
             return ", offset=" + index;
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Synthetic.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Synthetic.java
index 3683fd6437e..c7fef8fcebc 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Synthetic.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Synthetic.java
@@ -52,7 +52,7 @@ public final class Synthetic extends Attribute {
     }
 
     /**
-     * Construct object from input stream.
+     * Constructs object from input stream.
      *
      * @param nameIndex Index in constant pool to CONSTANT_Utf8
      * @param length Content length in bytes
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Utility.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Utility.java
index 12dbbe4828a..6967dcefd94 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Utility.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Utility.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -43,7 +43,7 @@ import com.sun.org.apache.bcel.internal.util.ByteSequence;
 /**
  * Utility functions that do not really belong to any class in particular.
  *
- * @LastModified: Feb 2023
+ * @LastModified: Sept 2025
  */
 // @since 6.0 methods are no longer final
 public abstract class Utility {
@@ -51,7 +51,7 @@ public abstract class Utility {
     /**
      * Decode characters into bytes. Used by decode()
      */
-    private static class JavaReader extends FilterReader {
+    private static final class JavaReader extends FilterReader {
 
         public JavaReader(final Reader in) {
             super(in);
@@ -88,10 +88,10 @@ public abstract class Utility {
     }
 
     /**
-     * Encode bytes into valid java identifier characters. Used by
+     * Encode bytes into valid Java identifier characters. Used by
      * encode()
      */
-    private static class JavaWriter extends FilterWriter {
+    private static final class JavaWriter extends FilterWriter {
 
         public JavaWriter(final Writer out) {
             super(out);
@@ -437,7 +437,9 @@ public abstract class Utility {
         case Const.NEW:
         case Const.CHECKCAST:
             buf.append("\t");
-            //$FALL-THROUGH$
+            index = bytes.readUnsignedShort();
+            buf.append("\t<").append(constantPool.constantToString(index, Const.CONSTANT_Class)).append(">").append(verbose ? " (" + index + ")" : "");
+            break;
         case Const.INSTANCEOF:
             index = bytes.readUnsignedShort();
             buf.append("\t<").append(constantPool.constantToString(index, Const.CONSTANT_Class)).append(">").append(verbose ? " (" + index + ")" : "");
@@ -864,7 +866,7 @@ public abstract class Utility {
             // Skip any type arguments to read argument declarations between '(' and ')'
             index = signature.indexOf('(') + 1;
             if (index <= 0) {
-                throw new ClassFormatException("Invalid method signature: " + signature);
+                throw new InvalidMethodSignatureException(signature);
             }
             while (signature.charAt(index) != ')') {
                 vec.add(typeSignatureToString(signature.substring(index), chopit));
@@ -872,7 +874,7 @@ public abstract class Utility {
                 index += unwrap(CONSUMER_CHARS); // update position
             }
         } catch (final StringIndexOutOfBoundsException e) { // Should never occur
-            throw new ClassFormatException("Invalid method signature: " + signature, e);
+            throw new InvalidMethodSignatureException(signature, e);
         }
         return vec.toArray(Const.EMPTY_STRING_ARRAY);
     }
@@ -903,11 +905,11 @@ public abstract class Utility {
             // Read return type after ')'
             index = signature.lastIndexOf(')') + 1;
             if (index <= 0) {
-                throw new ClassFormatException("Invalid method signature: " + signature);
+                throw new InvalidMethodSignatureException(signature);
             }
             type = typeSignatureToString(signature.substring(index), chopit);
         } catch (final StringIndexOutOfBoundsException e) { // Should never occur
-            throw new ClassFormatException("Invalid method signature: " + signature, e);
+            throw new InvalidMethodSignatureException(signature, e);
         }
         return type;
     }
@@ -959,7 +961,7 @@ public abstract class Utility {
             // Skip any type arguments to read argument declarations between '(' and ')'
             index = signature.indexOf('(') + 1;
             if (index <= 0) {
-                throw new ClassFormatException("Invalid method signature: " + signature);
+                throw new InvalidMethodSignatureException(signature);
             }
             while (signature.charAt(index) != ')') {
                 final String paramType = typeSignatureToString(signature.substring(index), chopit);
@@ -985,7 +987,7 @@ public abstract class Utility {
             // Read return type after ')'
             type = typeSignatureToString(signature.substring(index), chopit);
         } catch (final StringIndexOutOfBoundsException e) { // Should never occur
-            throw new ClassFormatException("Invalid method signature: " + signature, e);
+            throw new InvalidMethodSignatureException(signature, e);
         }
         // ignore any throws information in the signature
         if (buf.length() > 1) {
@@ -1172,7 +1174,7 @@ public abstract class Utility {
             type = typeParams + typeSignaturesToString(signature.substring(index), chopit, ')');
             index += unwrap(CONSUMER_CHARS); // update position
             // add return type
-            type = type + typeSignatureToString(signature.substring(index), chopit);
+            type += typeSignatureToString(signature.substring(index), chopit);
             index += unwrap(CONSUMER_CHARS); // update position
             // ignore any throws information in the signature
             return type;
@@ -1237,12 +1239,12 @@ public abstract class Utility {
         int index;
         try {
             if (signature.charAt(0) != '(') {
-                throw new ClassFormatException("Invalid method signature: " + signature);
+                throw new InvalidMethodSignatureException(signature);
             }
             index = signature.lastIndexOf(')') + 1;
             return typeOfSignature(signature.substring(index));
         } catch (final StringIndexOutOfBoundsException e) {
-            throw new ClassFormatException("Invalid method signature: " + signature, e);
+            throw new InvalidMethodSignatureException(signature, e);
         }
     }
 
@@ -1286,10 +1288,10 @@ public abstract class Utility {
             case '*':
                 return typeOfSignature(signature.substring(1));
             default:
-                throw new ClassFormatException("Invalid method signature: " + signature);
+                throw new InvalidMethodSignatureException(signature);
             }
         } catch (final StringIndexOutOfBoundsException e) {
-            throw new ClassFormatException("Invalid method signature: " + signature, e);
+            throw new InvalidMethodSignatureException(signature, e);
         }
     }
 
@@ -1469,8 +1471,8 @@ public abstract class Utility {
                 } else {
                     type.append(typeSignatureToString(signature.substring(consumedChars), chopit));
                     // update our consumed count by the number of characters the for type argument
-                    consumedChars = unwrap(Utility.CONSUMER_CHARS) + consumedChars;
-                    wrap(Utility.CONSUMER_CHARS, consumedChars);
+                    consumedChars = unwrap(CONSUMER_CHARS) + consumedChars;
+                    wrap(CONSUMER_CHARS, consumedChars);
                 }
 
                 // are there more TypeArguments?
@@ -1490,8 +1492,8 @@ public abstract class Utility {
                     } else {
                         type.append(typeSignatureToString(signature.substring(consumedChars), chopit));
                         // update our consumed count by the number of characters the for type argument
-                        consumedChars = unwrap(Utility.CONSUMER_CHARS) + consumedChars;
-                        wrap(Utility.CONSUMER_CHARS, consumedChars);
+                        consumedChars = unwrap(CONSUMER_CHARS) + consumedChars;
+                        wrap(CONSUMER_CHARS, consumedChars);
                     }
                 }
 
@@ -1508,14 +1510,14 @@ public abstract class Utility {
                     // update our consumed count by the number of characters the for type argument
                     // note that this count includes the "L" we added, but that is ok
                     // as it accounts for the "." we didn't consume
-                    consumedChars = unwrap(Utility.CONSUMER_CHARS) + consumedChars;
-                    wrap(Utility.CONSUMER_CHARS, consumedChars);
+                    consumedChars = unwrap(CONSUMER_CHARS) + consumedChars;
+                    wrap(CONSUMER_CHARS, consumedChars);
                     return type.toString();
                 }
                 if (signature.charAt(consumedChars) != ';') {
                     throw new ClassFormatException("Invalid signature: " + signature);
                 }
-                wrap(Utility.CONSUMER_CHARS, consumedChars + 1); // remove final ";"
+                wrap(CONSUMER_CHARS, consumedChars + 1); // remove final ";"
                 return type.toString();
             }
             case 'S':
@@ -1536,9 +1538,9 @@ public abstract class Utility {
                 // The rest of the string denotes a ''
                 type = typeSignatureToString(signature.substring(n), chopit);
                 // corrected concurrent private static field acess
-                // Utility.consumed_chars += consumed_chars; is replaced by:
-                final int temp = unwrap(Utility.CONSUMER_CHARS) + consumedChars;
-                wrap(Utility.CONSUMER_CHARS, temp);
+                // consumed_chars += consumed_chars; is replaced by:
+                final int temp = unwrap(CONSUMER_CHARS) + consumedChars;
+                wrap(CONSUMER_CHARS, temp);
                 return type + brackets.toString();
             }
             case 'V':
@@ -1552,11 +1554,11 @@ public abstract class Utility {
     }
 
     private static int unwrap(final ThreadLocal tl) {
-        return tl.get();
+        return tl.get().intValue();
     }
 
     private static void wrap(final ThreadLocal tl, final int value) {
-        tl.set(value);
+        tl.set(Integer.valueOf(value));
     }
 
 }
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Visitor.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Visitor.java
index 74cb8400d3e..1f6fe9c96ee 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Visitor.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/Visitor.java
@@ -217,11 +217,32 @@ public interface Visitor {
      */
     void visitParameterAnnotation(ParameterAnnotations obj);
 
+
     /**
      * @since 6.0
      */
     void visitParameterAnnotationEntry(ParameterAnnotationEntry obj);
 
+    /**
+     * Visits a {@link Record} object.
+     *
+     * @param obj Record to visit
+     * @since 6.9.0
+     */
+    default void visitRecord(final Record obj) {
+        // empty
+    }
+
+    /**
+     * Visits a {@link RecordComponentInfo} object.
+     *
+     * @param record component to visit
+     * @since 6.9.0
+     */
+    default void visitRecordComponent(final RecordComponentInfo record) {
+     // noop
+    }
+
     void visitSignature(Signature obj);
 
     void visitSourceFile(SourceFile obj);
@@ -230,7 +251,18 @@ public interface Visitor {
 
     void visitStackMapEntry(StackMapEntry obj);
 
+    /**
+     * Visits a {@link StackMapType} object.
+     *
+     * @param obj object to visit
+     * @since 6.8.0
+     */
+    default void visitStackMapType(final StackMapType obj) {
+      // empty
+    }
+
     void visitSynthetic(Synthetic obj);
 
     void visitUnknown(Unknown obj);
+
 }
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/package-info.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/package-info.java
new file mode 100644
index 00000000000..4e8d383bcab
--- /dev/null
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/classfile/package-info.java
@@ -0,0 +1,25 @@
+/*
+ * reserved comment block
+ * DO NOT REMOVE OR ALTER!
+ */
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+/**
+ * Classes that describe the structure of a Java class file and a class file parser.
+ */
+package com.sun.org.apache.bcel.internal.classfile;
diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ARRAYLENGTH.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ARRAYLENGTH.java
index 2d7188e9174..db756700085 100644
--- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ARRAYLENGTH.java
+++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ARRAYLENGTH.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
  */
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -28,12 +28,12 @@ import com.sun.org.apache.bcel.internal.ExceptionConst;
  * 
  * Stack: ..., arrayref -> ..., length
  * 
- * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public class ARRAYLENGTH extends Instruction implements ExceptionThrower, StackProducer, StackConsumer /* since 6.0 */ { /** - * Get length of array + * Gets length of array */ public ARRAYLENGTH() { super(com.sun.org.apache.bcel.internal.Const.ARRAYLENGTH, (short) 1); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ATHROW.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ATHROW.java index bb2e953f850..07171fefde1 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ATHROW.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ATHROW.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -28,8 +28,10 @@ import com.sun.org.apache.bcel.internal.ExceptionConst; *
  * Stack: ..., objectref -> objectref
  * 
+ * + * @LastModified: Sept 2025 */ -public class ATHROW extends Instruction implements UnconditionalBranch, ExceptionThrower { +public class ATHROW extends Instruction implements UnconditionalBranch, ExceptionThrower, StackConsumer { /** * Throw exception @@ -48,6 +50,7 @@ public class ATHROW extends Instruction implements UnconditionalBranch, Exceptio public void accept(final Visitor v) { v.visitUnconditionalBranch(this); v.visitExceptionThrower(this); + v.visitStackConsumer(this); v.visitATHROW(this); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/AnnotationEntryGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/AnnotationEntryGen.java index ea01a837175..0fad6ea7389 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/AnnotationEntryGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/AnnotationEntryGen.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -28,6 +28,7 @@ import java.io.DataOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; import com.sun.org.apache.bcel.internal.classfile.AnnotationEntry; import com.sun.org.apache.bcel.internal.classfile.Attribute; @@ -37,10 +38,11 @@ import com.sun.org.apache.bcel.internal.classfile.RuntimeInvisibleAnnotations; import com.sun.org.apache.bcel.internal.classfile.RuntimeInvisibleParameterAnnotations; import com.sun.org.apache.bcel.internal.classfile.RuntimeVisibleAnnotations; import com.sun.org.apache.bcel.internal.classfile.RuntimeVisibleParameterAnnotations; +import jdk.xml.internal.Utils; /** * @since 6.0 - * @LastModified: Jan 2020 + * @LastModified: Sept 2025 */ public class AnnotationEntryGen { @@ -53,7 +55,7 @@ public class AnnotationEntryGen { * @param annotationEntryGens An array of AnnotationGen objects */ static Attribute[] getAnnotationAttributes(final ConstantPoolGen cp, final AnnotationEntryGen[] annotationEntryGens) { - if (annotationEntryGens.length == 0) { + if (annotationEntryGens == null && annotationEntryGens.length == 0) { return Attribute.EMPTY_ARRAY; } @@ -255,11 +257,7 @@ public class AnnotationEntryGen { } private List copyValues(final ElementValuePair[] in, final ConstantPoolGen cpool, final boolean copyPoolEntries) { - final List out = new ArrayList<>(); - for (final ElementValuePair nvp : in) { - out.add(new ElementValuePairGen(nvp, cpool, copyPoolEntries)); - } - return out; + return Utils.streamOfIfNonNull(in).map(nvp -> new ElementValuePairGen(nvp, cpool, copyPoolEntries)).collect(Collectors.toList()); } public void dump(final DataOutputStream dos) throws IOException { @@ -286,18 +284,20 @@ public class AnnotationEntryGen { } public final String getTypeName() { - return getTypeSignature();// BCELBUG: Should I use this instead? + return getTypeSignature(); // BCELBUG: Should I use this instead? // Utility.signatureToString(getTypeSignature()); } public final String getTypeSignature() { - // ConstantClass c = (ConstantClass)cpool.getConstant(typeIndex); + // ConstantClass c = (ConstantClass) cpool.getConstant(typeIndex); final ConstantUtf8 utf8 = (ConstantUtf8) cpool.getConstant(typeIndex/* c.getNameIndex() */); return utf8.getBytes(); } /** - * Returns list of ElementNameValuePair objects + * Returns list of ElementNameValuePair objects. + * + * @return list of ElementNameValuePair objects. */ public List getValues() { return evs; diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayElementValueGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayElementValueGen.java index 71374877efe..59b774a9afc 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayElementValueGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayElementValueGen.java @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -25,12 +24,15 @@ import java.io.DataOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; import com.sun.org.apache.bcel.internal.classfile.ArrayElementValue; import com.sun.org.apache.bcel.internal.classfile.ElementValue; +import jdk.xml.internal.Utils; /** * @since 6.0 + * @LastModified: Sept 2025 */ public class ArrayElementValueGen extends ElementValueGen { // J5TODO: Should we make this an array or a list? A list would be easier to @@ -46,7 +48,7 @@ public class ArrayElementValueGen extends ElementValueGen { evalues = new ArrayList<>(); final ElementValue[] in = value.getElementValuesArray(); for (final ElementValue element : in) { - evalues.add(ElementValueGen.copy(element, cpool, copyPoolEntries)); + evalues.add(copy(element, cpool, copyPoolEntries)); } } @@ -55,15 +57,12 @@ public class ArrayElementValueGen extends ElementValueGen { evalues = new ArrayList<>(); } - public ArrayElementValueGen(final int type, final ElementValue[] datums, final ConstantPoolGen cpool) { + public ArrayElementValueGen(final int type, final ElementValue[] elementValues, final ConstantPoolGen cpool) { super(type, cpool); if (type != ARRAY) { throw new IllegalArgumentException("Only element values of type array can be built with this ctor - type specified: " + type); } - this.evalues = new ArrayList<>(); - for (final ElementValue datum : datums) { - evalues.add(ElementValueGen.copy(datum, cpool, true)); - } + this.evalues = Utils.streamOfIfNonNull(elementValues).map(e -> copy(e, cpool, true)).collect(Collectors.toList()); } public void addElement(final ElementValueGen gen) { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayType.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayType.java index 138999ebe90..78a676e875e 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayType.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ArrayType.java @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -24,6 +23,8 @@ import com.sun.org.apache.bcel.internal.Const; /** * Denotes array type, such as int[][] + * + * @LastModified: Sept 2025 */ public final class ArrayType extends ReferenceType { @@ -43,7 +44,7 @@ public final class ArrayType extends ReferenceType { /** * Convenience constructor for reference array type, e.g. Object[] * - * @param className complete name of class (java.lang.String, e.g.) + * @param className complete name of class ({@link String}, for example) * @param dimensions array dimensions */ public ArrayType(final String className, final int dimensions) { @@ -56,6 +57,7 @@ public final class ArrayType extends ReferenceType { * @param type type of array (may be an array itself) * @param dimensions array dimensions */ + @SuppressWarnings("deprecation") //signature public ArrayType(final Type type, final int dimensions) { super(Const.T_ARRAY, ""); if (dimensions < 1 || dimensions > Const.MAX_BYTE) { @@ -79,7 +81,7 @@ public final class ArrayType extends ReferenceType { buf.append('['); } buf.append(basicType.getSignature()); - super.setSignature(buf.toString()); + this.signature = buf.toString(); } /** diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BranchHandle.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BranchHandle.java index 91ab9ac5463..f489f9a7658 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BranchHandle.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/BranchHandle.java @@ -63,7 +63,7 @@ public final class BranchHandle extends InstructionHandle { } /** - * Set new contents. Old instruction is disposed and may not be used anymore. + * Sets new contents. Old instruction is disposed and may not be used anymore. */ @Override // This is only done in order to apply the additional type check; could be merged with super impl. public void setInstruction(final Instruction i) { // TODO could be package-protected? diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CPInstruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CPInstruction.java index 1dfd244141a..ff45e5cde93 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CPInstruction.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CPInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -35,7 +35,7 @@ import com.sun.org.apache.bcel.internal.util.ByteSequence; * @see LDC * @see INVOKEVIRTUAL * - * @LastModified: Jan 2020 + * @LastModified: Sept 2025 */ public abstract class CPInstruction extends Instruction implements TypedInstruction, IndexedInstruction { @@ -104,7 +104,7 @@ public abstract class CPInstruction extends Instruction implements TypedInstruct } /** - * Set the index to constant pool. + * Sets the index to constant pool. * * @param index in constant pool. */ diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassElementValueGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassElementValueGen.java index 1c1c032dbd5..8e024eebaa4 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassElementValueGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassElementValueGen.java @@ -48,12 +48,12 @@ public class ClassElementValueGen extends ElementValueGen { } protected ClassElementValueGen(final int typeIdx, final ConstantPoolGen cpool) { - super(ElementValueGen.CLASS, cpool); + super(CLASS, cpool); this.idx = typeIdx; } public ClassElementValueGen(final ObjectType t, final ConstantPoolGen cpool) { - super(ElementValueGen.CLASS, cpool); + super(CLASS, cpool); // this.idx = cpool.addClass(t); idx = cpool.addUtf8(t.getSignature()); } @@ -67,9 +67,9 @@ public class ClassElementValueGen extends ElementValueGen { public String getClassString() { final ConstantUtf8 cu8 = (ConstantUtf8) getConstantPool().getConstant(idx); return cu8.getBytes(); - // ConstantClass c = (ConstantClass)getConstantPool().getConstant(idx); + // ConstantClass c = (ConstantClass) getConstantPool().getConstant(idx); // ConstantUtf8 utf8 = - // (ConstantUtf8)getConstantPool().getConstant(c.getNameIndex()); + // (ConstantUtf8) getConstantPool().getConstant(c.getNameIndex()); // return utf8.getBytes(); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassGen.java index acaf4519567..debf930fe90 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ClassGen.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -40,40 +40,37 @@ import com.sun.org.apache.bcel.internal.classfile.Utility; import com.sun.org.apache.bcel.internal.util.BCELComparator; /** - * Template class for building up a java class. May be initialized with an existing java class (file). + * Template class for building up a java class. May be initialized with an existing Java class (file). * * @see JavaClass - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public class ClassGen extends AccessFlags implements Cloneable { - private static BCELComparator bcelComparator = new BCELComparator() { + private static BCELComparator bcelComparator = new BCELComparator() { @Override - public boolean equals(final Object o1, final Object o2) { - final ClassGen THIS = (ClassGen) o1; - final ClassGen THAT = (ClassGen) o2; - return Objects.equals(THIS.getClassName(), THAT.getClassName()); + public boolean equals(final ClassGen a, final ClassGen b) { + return a == b || a != null && b != null && Objects.equals(a.getClassName(), b.getClassName()); } @Override - public int hashCode(final Object o) { - final ClassGen THIS = (ClassGen) o; - return THIS.getClassName().hashCode(); + public int hashCode(final ClassGen o) { + return o != null ? Objects.hashCode(o.getClassName()) : 0; } }; /** * @return Comparison strategy object */ - public static BCELComparator getComparator() { + public static BCELComparator getComparator() { return bcelComparator; } /** * @param comparator Comparison strategy object */ - public static void setComparator(final BCELComparator comparator) { + public static void setComparator(final BCELComparator comparator) { bcelComparator = comparator; } @@ -101,7 +98,7 @@ public class ClassGen extends AccessFlags implements Cloneable { private List observers; /** - * Initialize with existing class. + * Constructs a new instance from an existing class. * * @param clazz JavaClass object (e.g. read from file) */ @@ -118,15 +115,26 @@ public class ClassGen extends AccessFlags implements Cloneable { final Attribute[] attributes = clazz.getAttributes(); // J5TODO: Could make unpacking lazy, done on first reference final AnnotationEntryGen[] annotations = unpackAnnotations(attributes); - Collections.addAll(interfaceList, clazz.getInterfaceNames()); - for (final Attribute attribute : attributes) { - if (!(attribute instanceof Annotations)) { - addAttribute(attribute); + final String[] interfaceNames = clazz.getInterfaceNames(); + if (interfaceNames != null) { + Collections.addAll(interfaceList, interfaceNames); + } + if (attributes != null) { + for (final Attribute attribute : attributes) { + if (!(attribute instanceof Annotations)) { + addAttribute(attribute); + } } } Collections.addAll(annotationList, annotations); - Collections.addAll(methodList, clazz.getMethods()); - Collections.addAll(fieldList, clazz.getFields()); + final Method[] methods = clazz.getMethods(); + if (methods != null) { + Collections.addAll(methodList, methods); + } + final Field[] fields = clazz.getFields(); + if (fields != null) { + Collections.addAll(fieldList, fields); + } } /** @@ -242,7 +250,7 @@ public class ClassGen extends AccessFlags implements Cloneable { try { return super.clone(); } catch (final CloneNotSupportedException e) { - throw new Error("Clone Not Supported"); // never happens + throw new UnsupportedOperationException("Clone Not Supported", e); // never happens } } @@ -282,7 +290,7 @@ public class ClassGen extends AccessFlags implements Cloneable { */ @Override public boolean equals(final Object obj) { - return bcelComparator.equals(this, obj); + return obj instanceof ClassGen && bcelComparator.equals(this, (ClassGen) obj); } // J5TODO: Should we make calling unpackAnnotations() lazy and put it in here? @@ -379,7 +387,7 @@ public class ClassGen extends AccessFlags implements Cloneable { } /** - * Return value as defined by given BCELComparator strategy. By default return the hashcode of the class name. + * Return value as defined by given BCELComparator strategy. By default return the hash code of the class name. * * @see Object#hashCode() */ @@ -478,7 +486,7 @@ public class ClassGen extends AccessFlags implements Cloneable { } /** - * Set major version number of class file, default value is 45 (JDK 1.1) + * Sets major version number of class file, default value is 45 (JDK 1.1) * * @param major major version number */ @@ -492,11 +500,13 @@ public class ClassGen extends AccessFlags implements Cloneable { public void setMethods(final Method[] methods) { methodList.clear(); - Collections.addAll(methodList, methods); + if (methods != null) { + Collections.addAll(methodList, methods); + } } /** - * Set minor version number of class file, default value is 3 (JDK 1.1) + * Sets minor version number of class file, default value is 3 (JDK 1.1) * * @param minor minor version number */ @@ -515,17 +525,19 @@ public class ClassGen extends AccessFlags implements Cloneable { } /** - * Look for attributes representing annotations and unpack them. + * Unpacks attributes representing annotations. */ - private AnnotationEntryGen[] unpackAnnotations(final Attribute[] attrs) { + private AnnotationEntryGen[] unpackAnnotations(final Attribute[] attributes) { final List annotationGenObjs = new ArrayList<>(); - for (final Attribute attr : attrs) { - if (attr instanceof RuntimeVisibleAnnotations) { - final RuntimeVisibleAnnotations rva = (RuntimeVisibleAnnotations) attr; - rva.forEach(a -> annotationGenObjs.add(new AnnotationEntryGen(a, getConstantPool(), false))); - } else if (attr instanceof RuntimeInvisibleAnnotations) { - final RuntimeInvisibleAnnotations ria = (RuntimeInvisibleAnnotations) attr; - ria.forEach(a -> annotationGenObjs.add(new AnnotationEntryGen(a, getConstantPool(), false))); + if (attributes != null) { + for (final Attribute attr : attributes) { + if (attr instanceof RuntimeVisibleAnnotations) { + final RuntimeVisibleAnnotations rva = (RuntimeVisibleAnnotations) attr; + rva.forEach(a -> annotationGenObjs.add(new AnnotationEntryGen(a, getConstantPool(), false))); + } else if (attr instanceof RuntimeInvisibleAnnotations) { + final RuntimeInvisibleAnnotations ria = (RuntimeInvisibleAnnotations) attr; + ria.forEach(a -> annotationGenObjs.add(new AnnotationEntryGen(a, getConstantPool(), false))); + } } } return annotationGenObjs.toArray(AnnotationEntryGen.EMPTY_ARRAY); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CodeExceptionGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CodeExceptionGen.java index fa660954d15..2518131ccee 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CodeExceptionGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/CodeExceptionGen.java @@ -63,7 +63,7 @@ public final class CodeExceptionGen implements InstructionTargeter, Cloneable { try { return super.clone(); } catch (final CloneNotSupportedException e) { - throw new Error("Clone Not Supported"); // never happens + throw new UnsupportedOperationException("Clone Not Supported", e); // never happens } } @@ -81,7 +81,7 @@ public final class CodeExceptionGen implements InstructionTargeter, Cloneable { } /** - * Get CodeException object.
+ * Gets CodeException object.
* * This relies on that the instruction list has already been dumped to byte code or that the 'setPositions' methods * has been called for the instruction list. @@ -120,7 +120,7 @@ public final class CodeExceptionGen implements InstructionTargeter, Cloneable { } /* - * Set end of handler + * Sets end of handler * * @param endPc End of handled region (inclusive) */ @@ -130,7 +130,7 @@ public final class CodeExceptionGen implements InstructionTargeter, Cloneable { } /* - * Set handler code + * Sets handler code * * @param handlerPc Start of handler */ @@ -140,7 +140,7 @@ public final class CodeExceptionGen implements InstructionTargeter, Cloneable { } /* - * Set start of handler + * Sets start of handler * * @param startPc Start of handled region (inclusive) */ diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ElementValuePairGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ElementValuePairGen.java index bdc9c517a86..878f392b6b7 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ElementValuePairGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ElementValuePairGen.java @@ -44,7 +44,7 @@ public class ElementValuePairGen { // Could assert nvp.getNameString() points to the same thing as // constantPoolGen.getConstant(nvp.getNameIndex()) // if - // (!nvp.getNameString().equals(((ConstantUtf8)constantPoolGen.getConstant(nvp.getNameIndex())).getBytes())) + // (!nvp.getNameString().equals(((ConstantUtf8) constantPoolGen.getConstant(nvp.getNameIndex())).getBytes())) // { // throw new IllegalArgumentException("envp buggered"); // } @@ -86,7 +86,7 @@ public class ElementValuePairGen { } public final String getNameString() { - // ConstantString cu8 = (ConstantString)constantPoolGen.getConstant(nameIdx); + // ConstantString cu8 = (ConstantString) constantPoolGen.getConstant(nameIdx); return ((ConstantUtf8) constantPoolGen.getConstant(nameIdx)).getBytes(); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/EnumElementValueGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/EnumElementValueGen.java index 95ac794f2d7..95c00ed3813 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/EnumElementValueGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/EnumElementValueGen.java @@ -40,10 +40,8 @@ public class EnumElementValueGen extends ElementValueGen { public EnumElementValueGen(final EnumElementValue value, final ConstantPoolGen cpool, final boolean copyPoolEntries) { super(ENUM_CONSTANT, cpool); if (copyPoolEntries) { - typeIdx = cpool.addUtf8(value.getEnumTypeString());// was - // addClass(value.getEnumTypeString()); - valueIdx = cpool.addUtf8(value.getEnumValueString()); // was - // addString(value.getEnumValueString()); + typeIdx = cpool.addUtf8(value.getEnumTypeString()); // was addClass(value.getEnumTypeString()); + valueIdx = cpool.addUtf8(value.getEnumValueString()); // was addString(value.getEnumValueString()); } else { typeIdx = value.getTypeIndex(); valueIdx = value.getValueIndex(); @@ -55,7 +53,7 @@ public class EnumElementValueGen extends ElementValueGen { * This ctor is used for deserialization */ protected EnumElementValueGen(final int typeIdx, final int valueIdx, final ConstantPoolGen cpool) { - super(ElementValueGen.ENUM_CONSTANT, cpool); + super(ENUM_CONSTANT, cpool); if (super.getElementValueType() != ENUM_CONSTANT) { throw new IllegalArgumentException("Only element values of type enum can be built with this ctor - type specified: " + super.getElementValueType()); } @@ -64,9 +62,9 @@ public class EnumElementValueGen extends ElementValueGen { } public EnumElementValueGen(final ObjectType t, final String value, final ConstantPoolGen cpool) { - super(ElementValueGen.ENUM_CONSTANT, cpool); - typeIdx = cpool.addUtf8(t.getSignature());// was addClass(t); - valueIdx = cpool.addUtf8(value);// was addString(value); + super(ENUM_CONSTANT, cpool); + typeIdx = cpool.addUtf8(t.getSignature()); // was addClass(t); + valueIdx = cpool.addUtf8(value); // was addString(value); } @Override @@ -90,9 +88,9 @@ public class EnumElementValueGen extends ElementValueGen { public String getEnumTypeString() { // Constant cc = getConstantPool().getConstant(typeIdx); // ConstantClass cu8 = - // (ConstantClass)getConstantPool().getConstant(typeIdx); + // (ConstantClass) getConstantPool().getConstant(typeIdx); // return - // ((ConstantUtf8)getConstantPool().getConstant(cu8.getNameIndex())).getBytes(); + // ((ConstantUtf8) getConstantPool().getConstant(cu8.getNameIndex())).getBytes(); return ((ConstantUtf8) getConstantPool().getConstant(typeIdx)).getBytes(); // return Utility.signatureToString(cu8.getBytes()); } @@ -100,9 +98,9 @@ public class EnumElementValueGen extends ElementValueGen { public String getEnumValueString() { return ((ConstantUtf8) getConstantPool().getConstant(valueIdx)).getBytes(); // ConstantString cu8 = - // (ConstantString)getConstantPool().getConstant(valueIdx); + // (ConstantString) getConstantPool().getConstant(valueIdx); // return - // ((ConstantUtf8)getConstantPool().getConstant(cu8.getStringIndex())).getBytes(); + // ((ConstantUtf8) getConstantPool().getConstant(cu8.getStringIndex())).getBytes(); } public int getTypeIndex() { @@ -118,8 +116,8 @@ public class EnumElementValueGen extends ElementValueGen { final ConstantUtf8 cu8 = (ConstantUtf8) getConstantPool().getConstant(valueIdx); return cu8.getBytes(); // ConstantString cu8 = - // (ConstantString)getConstantPool().getConstant(valueIdx); + // (ConstantString) getConstantPool().getConstant(valueIdx); // return - // ((ConstantUtf8)getConstantPool().getConstant(cu8.getStringIndex())).getBytes(); + // ((ConstantUtf8) getConstantPool().getConstant(cu8.getStringIndex())).getBytes(); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ExceptionThrower.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ExceptionThrower.java index 86a0cad256c..2a488c85ede 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ExceptionThrower.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ExceptionThrower.java @@ -23,7 +23,7 @@ package com.sun.org.apache.bcel.internal.generic; /** * Denote an instruction that may throw a run-time or a linking exception (or both) during execution. This is not quite - * the truth as such; because all instructions may throw an java.lang.VirtualMachineError. These exceptions are omitted. + * the truth as such; because all instructions may throw a {@link VirtualMachineError}. These exceptions are omitted. * * The Lava Language Specification specifies exactly which RUN-TIME and which LINKING exceptions each * instruction may throw which is reflected by the implementers. Due to the structure of the JVM specification, it may diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGen.java index 9d1f4d41d93..30786370d29 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGen.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -40,37 +40,34 @@ import com.sun.org.apache.bcel.internal.util.BCELComparator; * to a field (which must of course be compatible with to the declared type). * * @see Field - * @LastModified: May 2021 + * @LastModified: Sept 2025 */ public class FieldGen extends FieldGenOrMethodGen { - private static BCELComparator bcelComparator = new BCELComparator() { + private static BCELComparator bcelComparator = new BCELComparator() { @Override - public boolean equals(final Object o1, final Object o2) { - final FieldGen THIS = (FieldGen) o1; - final FieldGen THAT = (FieldGen) o2; - return Objects.equals(THIS.getName(), THAT.getName()) && Objects.equals(THIS.getSignature(), THAT.getSignature()); + public boolean equals(final FieldGen a, final FieldGen b) { + return a == b || a != null && b != null && Objects.equals(a.getName(), b.getName()) && Objects.equals(a.getSignature(), b.getSignature()); } @Override - public int hashCode(final Object o) { - final FieldGen THIS = (FieldGen) o; - return THIS.getSignature().hashCode() ^ THIS.getName().hashCode(); + public int hashCode(final FieldGen o) { + return o != null ? Objects.hash(o.getSignature(), o.getName()) : 0; } }; /** - * @return Comparison strategy object + * @return Comparison strategy object. */ - public static BCELComparator getComparator() { + public static BCELComparator getComparator() { return bcelComparator; } /** - * @param comparator Comparison strategy object + * @param comparator Comparison strategy object. */ - public static void setComparator(final BCELComparator comparator) { + public static void setComparator(final BCELComparator comparator) { bcelComparator = comparator; } @@ -81,8 +78,8 @@ public class FieldGen extends FieldGenOrMethodGen { /** * Instantiate from existing field. * - * @param field Field object - * @param cp constant pool (must contain the same entries as the field's constant pool) + * @param field Field object. + * @param cp constant pool (must contain the same entries as the field's constant pool). */ public FieldGen(final Field field, final ConstantPoolGen cp) { this(field.getAccessFlags(), Type.getType(field.getSignature()), field.getName(), cp); @@ -187,11 +184,11 @@ public class FieldGen extends FieldGenOrMethodGen { */ @Override public boolean equals(final Object obj) { - return bcelComparator.equals(this, obj); + return obj instanceof FieldGen && bcelComparator.equals(this, (FieldGen) obj); } /** - * Get field object after having set up all necessary values. + * Gets field object after having set up all necessary values. */ public Field getField() { final String signature = getSignature(); @@ -207,10 +204,7 @@ public class FieldGen extends FieldGenOrMethodGen { } public String getInitValue() { - if (value != null) { - return value.toString(); - } - return null; + return Objects.toString(value, null); } @Override @@ -219,7 +213,7 @@ public class FieldGen extends FieldGenOrMethodGen { } /** - * Return value as defined by given BCELComparator strategy. By default return the hashcode of the field's name XOR + * Return value as defined by given BCELComparator strategy. By default return the hash code of the field's name XOR * signature. * * @see Object#hashCode() @@ -295,7 +289,7 @@ public class FieldGen extends FieldGenOrMethodGen { } /** - * Set (optional) initial value of field, otherwise it will be set to null/0/false by the JVM automatically. + * Sets (optional) initial value of field, otherwise it will be set to null/0/false by the JVM automatically. */ public void setInitValue(final String str) { checkType(ObjectType.getInstance("java.lang.String")); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGenOrMethodGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGenOrMethodGen.java index 6555392e9d4..bc1fbc8627e 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGenOrMethodGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldGenOrMethodGen.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -30,7 +30,7 @@ import com.sun.org.apache.bcel.internal.classfile.Attribute; /** * Super class for FieldGen and MethodGen objects, since they have some methods in common! * - * @LastModified: May 2021 + * @LastModified: Sept 2025 */ public abstract class FieldGenOrMethodGen extends AccessFlags implements NamedAndTyped, Cloneable { @@ -67,8 +67,10 @@ public abstract class FieldGenOrMethodGen extends AccessFlags implements NamedAn super(accessFlags); } - protected void addAll(final Attribute[] attrs) { - Collections.addAll(attributeList, attrs); + protected void addAll(final Attribute[] attributes) { + if (attributes != null) { + Collections.addAll(attributeList, attributes); + } } /** @@ -93,7 +95,7 @@ public abstract class FieldGenOrMethodGen extends AccessFlags implements NamedAn try { return super.clone(); } catch (final CloneNotSupportedException e) { - throw new Error("Clone Not Supported"); // never happens + throw new UnsupportedOperationException("Clone Not Supported", e); // never happens } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldOrMethod.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldOrMethod.java index 1c646f48292..87ba4cb913e 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldOrMethod.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/FieldOrMethod.java @@ -53,7 +53,6 @@ public abstract class FieldOrMethod extends CPInstruction implements LoadClass { * generated by Java 1.5, this answer is sometimes wrong (e.g., if the "clone()" method is called on an * array). A better idea is to use the {@link #getReferenceType(ConstantPoolGen)} method, which correctly * distinguishes between class types and array types. - * */ @Deprecated public String getClassName(final ConstantPoolGen cpg) { @@ -89,6 +88,9 @@ public abstract class FieldOrMethod extends CPInstruction implements LoadClass { if (rt instanceof ObjectType) { return (ObjectType) rt; } + if (rt instanceof ArrayType) { + return Type.OBJECT; + } throw new ClassGenException(rt.getClass().getCanonicalName() + " " + rt.getSignature() + " does not represent an ObjectType"); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ICONST.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ICONST.java index 5effd7edcd9..b3eb14a9ddf 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ICONST.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ICONST.java @@ -25,7 +25,6 @@ package com.sun.org.apache.bcel.internal.generic; *
  * Stack: ... -> ...,
  * 
- * */ public class ICONST extends Instruction implements ConstantPushInstruction { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKEDYNAMIC.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKEDYNAMIC.java index 2865a158de2..998d072e067 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKEDYNAMIC.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/INVOKEDYNAMIC.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -37,7 +37,7 @@ import com.sun.org.apache.bcel.internal.util.ByteSequence; * @see The * invokedynamic instruction in The Java Virtual Machine Specification * @since 6.0 - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public class INVOKEDYNAMIC extends InvokeInstruction { @@ -104,11 +104,11 @@ public class INVOKEDYNAMIC extends InvokeInstruction { } /** - * Since InvokeDynamic doesn't refer to a reference type, just return java.lang.Object, as that is the only type we can + * Since InvokeDynamic doesn't refer to a reference type, just return {@link Object}, as that is the only type we can * say for sure the reference will be. * * @param cpg the ConstantPoolGen used to create the instruction - * @return an ObjectType for java.lang.Object + * @return an ObjectType for {@link Object} * @since 6.1 */ @Override diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Instruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Instruction.java index 16c8e2444b4..a7124409f12 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Instruction.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Instruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -29,7 +29,7 @@ import com.sun.org.apache.bcel.internal.util.ByteSequence; /** * Abstract super class for all Java byte codes. * - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public abstract class Instruction implements Cloneable { @@ -461,7 +461,7 @@ public abstract class Instruction implements Cloneable { public Instruction copy() { Instruction i = null; // "Constant" instruction, no need to duplicate - if (InstructionConst.getInstruction(this.getOpcode()) != null) { + if (InstructionConst.getInstruction(getOpcode()) != null) { i = this; } else { try { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionConst.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionConst.java index 439268e35eb..7b95bfc99b1 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionConst.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionConst.java @@ -170,7 +170,7 @@ public final class InstructionConst { public static final LocalVariableInstruction ISTORE_2 = new ISTORE(2); /** - * Get object via its opcode, for immutable instructions like branch instructions entries are set to null. + * Gets object via its opcode, for immutable instructions like branch instructions entries are set to null. */ static final Instruction[] INSTRUCTIONS = new Instruction[256]; diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionFactory.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionFactory.java index 5e9220354c3..3c4b3e9f9da 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionFactory.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -30,11 +30,11 @@ import com.sun.org.apache.bcel.internal.Const; * * @see Const * @see InstructionConst - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public class InstructionFactory { - private static class MethodObject { + private static final class MethodObject { final Type[] argTypes; final Type resultType; @@ -53,10 +53,12 @@ public class InstructionFactory { private static final String FQCN_STRING_BUFFER = "java.lang.StringBuffer"; - // N.N. These must agree with the order of Constants.T_CHAR through T_LONG - private static final String[] shortNames = {"C", "F", "D", "B", "S", "I", "L"}; + /** + * These must agree with the order of Constants.T_CHAR through T_LONG. + */ + private static final String[] SHORT_NAMES = {"C", "F", "D", "B", "S", "I", "L"}; - private static final MethodObject[] appendMethodObjects = { + private static final MethodObject[] APPEND_METHOD_OBJECTS = { new MethodObject(FQCN_STRING_BUFFER, APPEND, Type.STRINGBUFFER, new Type[] { Type.STRING }), new MethodObject(FQCN_STRING_BUFFER, APPEND, Type.STRINGBUFFER, new Type[] { Type.OBJECT }), null, null, // indices 2, 3 new MethodObject(FQCN_STRING_BUFFER, APPEND, Type.STRINGBUFFER, new Type[] { Type.BOOLEAN }), @@ -484,7 +486,7 @@ public class InstructionFactory { public Instruction createAppend(final Type type) { final byte t = type.getType(); if (isString(type)) { - return createInvoke(appendMethodObjects[0], Const.INVOKEVIRTUAL); + return createInvoke(APPEND_METHOD_OBJECTS[0], Const.INVOKEVIRTUAL); } switch (t) { case Const.T_BOOLEAN: @@ -495,10 +497,10 @@ public class InstructionFactory { case Const.T_SHORT: case Const.T_INT: case Const.T_LONG: - return createInvoke(appendMethodObjects[t], Const.INVOKEVIRTUAL); + return createInvoke(APPEND_METHOD_OBJECTS[t], Const.INVOKEVIRTUAL); case Const.T_ARRAY: case Const.T_OBJECT: - return createInvoke(appendMethodObjects[1], Const.INVOKEVIRTUAL); + return createInvoke(APPEND_METHOD_OBJECTS[1], Const.INVOKEVIRTUAL); default: throw new IllegalArgumentException("No append for this type? " + type); } @@ -515,7 +517,7 @@ public class InstructionFactory { if (dest == Const.T_LONG && (src == Const.T_CHAR || src == Const.T_BYTE || src == Const.T_SHORT)) { src = Const.T_INT; } - final String name = "com.sun.org.apache.bcel.internal.generic." + shortNames[src - Const.T_CHAR] + "2" + shortNames[dest - Const.T_CHAR]; + final String name = "com.sun.org.apache.bcel.internal.generic." + SHORT_NAMES[src - Const.T_CHAR] + "2" + SHORT_NAMES[dest - Const.T_CHAR]; Instruction i = null; try { i = (Instruction) Class.forName(name).getDeclaredConstructor().newInstance();; @@ -642,8 +644,10 @@ public class InstructionFactory { int index; int nargs = 0; final String signature = Type.getMethodSignature(retType, argTypes); - for (final Type argType : argTypes) { - nargs += argType.getSize(); + if (argTypes != null) { + for (final Type argType : argTypes) { + nargs += argType.getSize(); + } } if (useInterface) { index = cp.addInterfaceMethodref(className, name, signature); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionHandle.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionHandle.java index 5e962354d16..2c94b770265 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionHandle.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionHandle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -38,7 +38,7 @@ import com.sun.org.apache.bcel.internal.classfile.Utility; * @see Instruction * @see BranchHandle * @see InstructionList - * @LastModified: May 2021 + * @LastModified: Sept 2025 */ public class InstructionHandle { @@ -118,7 +118,7 @@ public class InstructionHandle { if (targeters == null) { targeters = new HashSet<>(); } - // if(!targeters.contains(t)) + // if (!targeters.contains(t)) targeters.add(t); } @@ -135,15 +135,12 @@ public class InstructionHandle { } /** - * Get attribute of an instruction handle. + * Gets attribute of an instruction handle. * * @param key the key object to store/retrieve the attribute */ public Object getAttribute(final Object key) { - if (attributes != null) { - return attributes.get(key); - } - return null; + return attributes != null ? attributes.get(key) : null; } /** @@ -247,7 +244,7 @@ public class InstructionHandle { } /** - * Set the position, i.e., the byte code offset of the contained instruction. + * Sets the position, i.e., the byte code offset of the contained instruction. */ void setPosition(final int pos) { i_position = pos; diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionList.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionList.java index 7ffc3a8228e..579efc9fe3b 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionList.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionList.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -33,6 +33,7 @@ import java.util.NoSuchElementException; import com.sun.org.apache.bcel.internal.Const; import com.sun.org.apache.bcel.internal.classfile.Constant; import com.sun.org.apache.bcel.internal.util.ByteSequence; +import jdk.xml.internal.Utils; /** * This class is a container for a list of Instruction objects. Instructions can be @@ -46,7 +47,7 @@ import com.sun.org.apache.bcel.internal.util.ByteSequence; * @see Instruction * @see InstructionHandle * @see BranchHandle - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public class InstructionList implements Iterable { @@ -60,23 +61,25 @@ public class InstructionList implements Iterable { * @return target position's instruction handle if available */ public static InstructionHandle findHandle(final InstructionHandle[] ihs, final int[] pos, final int count, final int target) { - int l = 0; - int r = count - 1; - /* - * Do a binary search since the pos array is orderd. - */ - do { - final int i = l + r >>> 1; - final int j = pos[i]; - if (j == target) { - return ihs[i]; - } - if (target < j) { - r = i - 1; - } else { - l = i + 1; - } - } while (l <= r); + if (ihs != null && pos != null) { + int l = 0; + int r = count - 1; + /* + * Do a binary search since the pos array is orderd. + */ + do { + final int i = l + r >>> 1; + final int j = pos[i]; + if (j == target) { + return ihs[i]; + } + if (target < j) { + r = i - 1; + } else { + l = i + 1; + } + } while (l <= r); + } return null; } @@ -513,7 +516,7 @@ public class InstructionList implements Iterable { } /** - * Get instruction handle for instruction at byte code position pos. This only works properly, if the list is freshly + * Gets instruction handle for instruction at byte code position pos. This only works properly, if the list is freshly * initialized from a byte array or setPositions() has been called before this method. * * @param pos byte code position to search for @@ -605,7 +608,7 @@ public class InstructionList implements Iterable { } /** - * Get positions (offsets) of all instructions in the list. This relies on that the list has been freshly created from + * Gets positions (offsets) of all instructions in the list. This relies on that the list has been freshly created from * an byte code array, or that setPositions() has been called. Otherwise this may be inaccurate. * * @return array containing all instruction's offset in byte code @@ -959,7 +962,7 @@ public class InstructionList implements Iterable { * @see MethodGen */ public void redirectExceptionHandlers(final CodeExceptionGen[] exceptions, final InstructionHandle oldTarget, final InstructionHandle newTarget) { - for (final CodeExceptionGen exception : exceptions) { + Utils.streamOfIfNonNull(exceptions).forEach(exception -> { if (exception.getStartPC() == oldTarget) { exception.setStartPC(newTarget); } @@ -969,7 +972,7 @@ public class InstructionList implements Iterable { if (exception.getHandlerPC() == oldTarget) { exception.setHandlerPC(newTarget); } - } + }); } /** @@ -981,16 +984,14 @@ public class InstructionList implements Iterable { * @see MethodGen */ public void redirectLocalVariables(final LocalVariableGen[] lg, final InstructionHandle oldTarget, final InstructionHandle newTarget) { - for (final LocalVariableGen element : lg) { - final InstructionHandle start = element.getStart(); - final InstructionHandle end = element.getEnd(); - if (start == oldTarget) { + Utils.streamOfIfNonNull(lg).forEach(element -> { + if (element.getStart() == oldTarget) { element.setStart(newTarget); } - if (end == oldTarget) { + if (element.getEnd() == oldTarget) { element.setEnd(newTarget); } - } + }); } /** @@ -1120,7 +1121,7 @@ public class InstructionList implements Iterable { ih.setPosition(index); pos[count++] = index; /* - * Get an estimate about how many additional bytes may be added, because BranchInstructions may have variable length + * Gets an estimate about how many additional bytes may be added, because BranchInstructions may have variable length * depending on the target offset (short vs. int) or alignment issues (TABLESWITCH and LOOKUPSWITCH). */ switch (i.getOpcode()) { @@ -1132,11 +1133,14 @@ public class InstructionList implements Iterable { case Const.LOOKUPSWITCH: maxAdditionalBytes += 3; break; + default: + // TODO should this be an error? + break; } index += i.getLength(); } /* - * Pass 2: Expand the variable-length (Branch)Instructions depending on the target offset (short or int) and ensure that + * Pass 2: Expand the variable-length (Branch) Instructions depending on the target offset (short or int) and ensure that * branch targets are within this list. */ for (InstructionHandle ih = start; ih != null; ih = ih.getNext()) { @@ -1152,8 +1156,7 @@ public class InstructionList implements Iterable { pos[count++] = index; index += i.getLength(); } - bytePositions = new int[count]; // Trim to proper size - System.arraycopy(pos, 0, bytePositions, 0, count); + bytePositions = Arrays.copyOfRange(pos, 0, count); // Trim to proper size } /** diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionTargeter.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionTargeter.java index 5146408ef49..0681476b5ee 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionTargeter.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/InstructionTargeter.java @@ -22,7 +22,7 @@ package com.sun.org.apache.bcel.internal.generic; /** - * Denote that a class targets InstructionHandles within an InstructionList. Namely the following implementers: + * Denotes that a class targets InstructionHandles within an InstructionList. * * @see BranchHandle * @see LocalVariableGen @@ -33,9 +33,12 @@ public interface InstructionTargeter { // static final InstructionTargeter[] EMPTY_ARRAY = new InstructionTargeter[0]; /** - * Checks whether this targeter targets the specified instruction handle. + * Tests whether this targeter targets the specified instruction handle. + * + * @param instructionHandle the instruction handle to test. + * @return whether this targeter targets the specified instruction handle. */ - boolean containsTarget(InstructionHandle ih); + boolean containsTarget(InstructionHandle instructionHandle); /** * Replaces the target of this targeter from this old handle to the new handle. diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LCMP.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LCMP.java index c517b492f0a..188ac95f6ef 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LCMP.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LCMP.java @@ -27,7 +27,6 @@ package com.sun.org.apache.bcel.internal.generic; *
  * Stack: ..., value1.word1, value1.word2, value2.word1, value2.word2 -> ..., result <= -1, 0, 1>
  * 
- * */ public class LCMP extends Instruction implements TypedInstruction, StackProducer, StackConsumer { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDC.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDC.java index d95bade23bd..13ca0a84cfa 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDC.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LDC.java @@ -94,6 +94,8 @@ public class LDC extends CPInstruction implements PushInstruction, ExceptionThro return Type.INT; case com.sun.org.apache.bcel.internal.Const.CONSTANT_Class: return Type.CLASS; + case com.sun.org.apache.bcel.internal.Const.CONSTANT_Dynamic: + return Type.OBJECT; default: // Never reached throw new IllegalArgumentException("Unknown or invalid constant type at " + super.getIndex()); } @@ -113,7 +115,10 @@ public class LDC extends CPInstruction implements PushInstruction, ExceptionThro case com.sun.org.apache.bcel.internal.Const.CONSTANT_Class: final int nameIndex = ((com.sun.org.apache.bcel.internal.classfile.ConstantClass) c).getNameIndex(); c = cpg.getConstantPool().getConstant(nameIndex); - return Type.getType(((com.sun.org.apache.bcel.internal.classfile.ConstantUtf8) c).getBytes()); + return Type.getType(Type.internalTypeNameToSignature(((com.sun.org.apache.bcel.internal.classfile.ConstantUtf8) c).getBytes())); + case com.sun.org.apache.bcel.internal.Const.CONSTANT_Dynamic: + // Really not sure what to return here, maybe a BootstrapMethod instance but how do we get it? + return c; default: // Never reached throw new IllegalArgumentException("Unknown or invalid constant type at " + super.getIndex()); } @@ -129,7 +134,7 @@ public class LDC extends CPInstruction implements PushInstruction, ExceptionThro } /** - * Set the index to constant pool and adjust size. + * Sets the index to constant pool and adjust size. */ @Override public final void setIndex(final int index) { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LineNumberGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LineNumberGen.java index 3773c21e7b3..68bb2abf513 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LineNumberGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LineNumberGen.java @@ -54,7 +54,7 @@ public class LineNumberGen implements InstructionTargeter, Cloneable { try { return super.clone(); } catch (final CloneNotSupportedException e) { - throw new Error("Clone Not Supported"); // never happens + throw new UnsupportedOperationException("Clone Not Supported", e); // never happens } } @@ -71,7 +71,7 @@ public class LineNumberGen implements InstructionTargeter, Cloneable { } /** - * Get LineNumber attribute. + * Gets LineNumber attribute. * * This relies on that the instruction list has already been dumped to byte code or that the 'setPositions' methods * has been called for the instruction list. diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableGen.java index 830564d42c9..71cfa0cf1c2 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableGen.java @@ -85,7 +85,7 @@ public class LocalVariableGen implements InstructionTargeter, NamedAndTyped, Clo try { return super.clone(); } catch (final CloneNotSupportedException e) { - throw new Error("Clone Not Supported"); // never happens + throw new UnsupportedOperationException("Clone Not Supported", e); // never happens } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableInstruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableInstruction.java index 67184c0b9f1..f952a65880b 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableInstruction.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/LocalVariableInstruction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -28,7 +28,7 @@ import com.sun.org.apache.bcel.internal.util.ByteSequence; /** * Abstract super class for instructions dealing with local variables. * - * @LastModified: May 2021 + * @LastModified: Sept 2025 */ public abstract class LocalVariableInstruction extends Instruction implements TypedInstruction, IndexedInstruction { @@ -162,7 +162,7 @@ public abstract class LocalVariableInstruction extends Instruction implements Ty } /** - * Set the local variable index. also updates opcode and length TODO Why? + * Sets the local variable index. also updates opcode and length TODO Why? * * @see #setIndexOnly(int) */ diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MethodGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MethodGen.java index f6e8333be79..be09b0a5159 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MethodGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/MethodGen.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -27,6 +27,7 @@ import java.util.HashMap; import java.util.List; import java.util.Objects; import java.util.Stack; +import java.util.stream.Collectors; import com.sun.org.apache.bcel.internal.Const; import com.sun.org.apache.bcel.internal.classfile.AnnotationEntry; @@ -46,6 +47,7 @@ import com.sun.org.apache.bcel.internal.classfile.ParameterAnnotations; import com.sun.org.apache.bcel.internal.classfile.RuntimeVisibleParameterAnnotations; import com.sun.org.apache.bcel.internal.classfile.Utility; import com.sun.org.apache.bcel.internal.util.BCELComparator; +import jdk.xml.internal.Utils; /** * Template class for building up a method. This is done by defining exception handlers, adding thrown exceptions, local @@ -57,7 +59,7 @@ import com.sun.org.apache.bcel.internal.util.BCELComparator; * * @see InstructionList * @see Method - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public class MethodGen extends FieldGenOrMethodGen { @@ -102,19 +104,16 @@ public class MethodGen extends FieldGenOrMethodGen { } } - private static BCELComparator bcelComparator = new BCELComparator() { + private static BCELComparator bcelComparator = new BCELComparator() { @Override - public boolean equals(final Object o1, final Object o2) { - final FieldGenOrMethodGen THIS = (FieldGenOrMethodGen) o1; - final FieldGenOrMethodGen THAT = (FieldGenOrMethodGen) o2; - return Objects.equals(THIS.getName(), THAT.getName()) && Objects.equals(THIS.getSignature(), THAT.getSignature()); + public boolean equals(final FieldGenOrMethodGen a, final FieldGenOrMethodGen b) { + return a == b || a != null && b != null && Objects.equals(a.getName(), b.getName()) && Objects.equals(a.getSignature(), b.getSignature()); } @Override - public int hashCode(final Object o) { - final FieldGenOrMethodGen THIS = (FieldGenOrMethodGen) o; - return THIS.getSignature().hashCode() ^ THIS.getName().hashCode(); + public int hashCode(final FieldGenOrMethodGen o) { + return o != null ? Objects.hash(o.getSignature(), o.getName()) : 0; } }; @@ -127,9 +126,9 @@ public class MethodGen extends FieldGenOrMethodGen { } /** - * @return Comparison strategy object + * @return Comparison strategy object. */ - public static BCELComparator getComparator() { + public static BCELComparator getComparator() { return bcelComparator; } @@ -206,9 +205,9 @@ public class MethodGen extends FieldGenOrMethodGen { } /** - * @param comparator Comparison strategy object + * @param comparator Comparison strategy object. */ - public static void setComparator(final BCELComparator comparator) { + public static void setComparator(final BCELComparator comparator) { bcelComparator = comparator; } @@ -636,7 +635,7 @@ public class MethodGen extends FieldGenOrMethodGen { */ @Override public boolean equals(final Object obj) { - return bcelComparator.equals(this, obj); + return obj instanceof FieldGenOrMethodGen && bcelComparator.equals(this, (FieldGenOrMethodGen) obj); } // J5TODO: Should paramAnnotations be an array of arrays? Rather than an array of lists, this @@ -790,7 +789,7 @@ public class MethodGen extends FieldGenOrMethodGen { } /** - * Get method object. Never forget to call setMaxStack() or setMaxStack(max), respectively, before calling this method + * Gets method object. Never forget to call setMaxStack() or setMaxStack(max), respectively, before calling this method * (the same applies for max locals). * * @return method object @@ -888,7 +887,7 @@ public class MethodGen extends FieldGenOrMethodGen { } /** - * Return value as defined by given BCELComparator strategy. By default return the hashcode of the method's name XOR + * Return value as defined by given BCELComparator strategy. By default return the hash code of the method's name XOR * signature. * * @see Object#hashCode() @@ -899,11 +898,7 @@ public class MethodGen extends FieldGenOrMethodGen { } private List makeMutableVersion(final AnnotationEntry[] mutableArray) { - final List result = new ArrayList<>(); - for (final AnnotationEntry element : mutableArray) { - result.add(new AnnotationEntryGen(element, getConstantPool(), false)); - } - return result; + return Utils.streamOfIfNonNull(mutableArray).map(ae -> new AnnotationEntryGen(ae, getConstantPool(), false)).collect(Collectors.toList()); } /** @@ -1027,10 +1022,8 @@ public class MethodGen extends FieldGenOrMethodGen { * * @since 6.5.0 */ - public void removeRuntimeAttributes(final Attribute[] attrs) { - for (final Attribute attr : attrs) { - removeAttribute(attr); - } + public void removeRuntimeAttributes(final Attribute[] attributes) { + Utils.streamOfIfNonNull(attributes).forEach(this::removeAttribute); } public void setArgumentName(final int i, final String name) { @@ -1038,7 +1031,7 @@ public class MethodGen extends FieldGenOrMethodGen { } public void setArgumentNames(final String[] argNames) { - this.argNames = argNames; + this.argNames = Utils.createEmptyArrayIfNull(argNames, String[].class); } public void setArgumentType(final int i, final Type type) { @@ -1046,7 +1039,7 @@ public class MethodGen extends FieldGenOrMethodGen { } public void setArgumentTypes(final Type[] argTypes) { - this.argTypes = argTypes; + this.argTypes = argTypes != null ? argTypes : Type.NO_ARGS; } public void setClassName(final String className) { // TODO could be package-protected? @@ -1084,7 +1077,7 @@ public class MethodGen extends FieldGenOrMethodGen { } /** - * Set maximum number of local variables. + * Sets maximum number of local variables. */ public void setMaxLocals(final int m) { maxLocals = m; @@ -1102,7 +1095,7 @@ public class MethodGen extends FieldGenOrMethodGen { } /** - * Set maximum stack size for this method. + * Sets maximum stack size for this method. */ public void setMaxStack(final int m) { // TODO could be package-protected? maxStack = m; diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ObjectType.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ObjectType.java index 46378a1b71e..622a3cdd961 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ObjectType.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ObjectType.java @@ -27,7 +27,7 @@ import com.sun.org.apache.bcel.internal.classfile.JavaClass; import com.sun.org.apache.bcel.internal.classfile.Utility; /** - * Denotes reference such as java.lang.String. + * Denotes reference such as {@link String}. */ public class ObjectType extends ReferenceType { @@ -47,7 +47,7 @@ public class ObjectType extends ReferenceType { /** * Constructs a new instance. * - * @param className fully qualified class name, e.g. java.lang.String + * @param className fully qualified class name, e.g. {@link String} */ public ObjectType(final String className) { super(Const.T_REFERENCE, "L" + Utility.packageToPath(className) + ";"); @@ -151,7 +151,7 @@ public class ObjectType extends ReferenceType { * @throws ClassNotFoundException if any of this class's superclasses can't be found */ public boolean subclassOf(final ObjectType superclass) throws ClassNotFoundException { - if (this.referencesInterfaceExact() || superclass.referencesInterfaceExact()) { + if (referencesInterfaceExact() || superclass.referencesInterfaceExact()) { return false; } return Repository.instanceOf(this.className, superclass.className); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/RET.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/RET.java index a7cacc7c165..99a1efbed16 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/RET.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/RET.java @@ -110,7 +110,7 @@ public class RET extends Instruction implements IndexedInstruction, TypedInstruc } /** - * Set index of local variable containg the return address + * Sets index of local variable containg the return address */ @Override public final void setIndex(final int n) { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ReferenceType.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ReferenceType.java index fe75792e213..9b94a1dcf2d 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ReferenceType.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/ReferenceType.java @@ -42,10 +42,10 @@ public abstract class ReferenceType extends Type { /** * This commutative operation returns the first common superclass (narrowest ReferenceType referencing a class, not an - * interface). If one of the types is a superclass of the other, the former is returned. If "this" is Type.NULL, then t - * is returned. If t is Type.NULL, then "this" is returned. If "this" equals t ['this.equals(t)'] "this" is returned. If - * "this" or t is an ArrayType, then Type.OBJECT is returned. If "this" or t is a ReferenceType referencing an - * interface, then Type.OBJECT is returned. If not all of the two classes' superclasses cannot be found, "null" is + * interface). If one of the types is a superclass of the other, the former is returned. If "this" is NULL, then t + * is returned. If t is NULL, then "this" is returned. If "this" equals t ['this.equals(t)'] "this" is returned. If + * "this" or t is an ArrayType, then {@link #OBJECT} is returned. If "this" or t is a ReferenceType referencing an + * interface, then {@link #OBJECT} is returned. If not all of the two classes' superclasses cannot be found, "null" is * returned. See the JVM specification edition 2, "4.9.2 The Bytecode Verifier". * * @deprecated use getFirstCommonSuperclass(ReferenceType t) which has slightly changed semantics. @@ -53,46 +53,46 @@ public abstract class ReferenceType extends Type { */ @Deprecated public ReferenceType firstCommonSuperclass(final ReferenceType t) throws ClassNotFoundException { - if (this.equals(Type.NULL)) { + if (equals(NULL)) { return t; } - if (t.equals(Type.NULL) || this.equals(t)) { + if (t.equals(NULL) || equals(t)) { return this; /* - * TODO: Above sounds a little arbitrary. On the other hand, there is no object referenced by Type.NULL so we can also - * say all the objects referenced by Type.NULL were derived from java.lang.Object. However, the Java Language's - * "instanceof" operator proves us wrong: "null" is not referring to an instance of java.lang.Object :) + * TODO: Above sounds a little arbitrary. On the other hand, there is no object referenced by {@link #NULL} so we can also + * say all the objects referenced by {@link #NULL} were derived from {@link Object}. However, the Java Language's + * "instanceof" operator proves us wrong: "null" is not referring to an instance of {@link Object} :) */ } if (this instanceof ArrayType || t instanceof ArrayType) { - return Type.OBJECT; - // TODO: Is there a proof of OBJECT being the direct ancestor of every ArrayType? + return OBJECT; + // TODO: Is there a proof of {@link #OBJECT} being the direct ancestor of every ArrayType? } return getFirstCommonSuperclassInternal(t); } /** * This commutative operation returns the first common superclass (narrowest ReferenceType referencing a class, not an - * interface). If one of the types is a superclass of the other, the former is returned. If "this" is Type.NULL, then t - * is returned. If t is Type.NULL, then "this" is returned. If "this" equals t ['this.equals(t)'] "this" is returned. If - * "this" or t is an ArrayType, then Type.OBJECT is returned; unless their dimensions match. Then an ArrayType of the + * interface). If one of the types is a superclass of the other, the former is returned. If "this" is NULL, then t + * is returned. If t is NULL, then "this" is returned. If "this" equals t ['this.equals(t)'] "this" is returned. If + * "this" or t is an ArrayType, then {@link #OBJECT} is returned; unless their dimensions match. Then an ArrayType of the * same number of dimensions is returned, with its basic type being the first common super class of the basic types of - * "this" and t. If "this" or t is a ReferenceType referencing an interface, then Type.OBJECT is returned. If not all of + * "this" and t. If "this" or t is a ReferenceType referencing an interface, then {@link #OBJECT} is returned. If not all of * the two classes' superclasses cannot be found, "null" is returned. See the JVM specification edition 2, "4.9.2 The * Bytecode Verifier". * * @throws ClassNotFoundException on failure to find superclasses of this type, or the type passed as a parameter */ public ReferenceType getFirstCommonSuperclass(final ReferenceType t) throws ClassNotFoundException { - if (this.equals(Type.NULL)) { + if (equals(NULL)) { return t; } - if (t.equals(Type.NULL) || this.equals(t)) { + if (t.equals(NULL) || equals(t)) { return this; /* - * TODO: Above sounds a little arbitrary. On the other hand, there is no object referenced by Type.NULL so we can also - * say all the objects referenced by Type.NULL were derived from java.lang.Object. However, the Java Language's - * "instanceof" operator proves us wrong: "null" is not referring to an instance of java.lang.Object :) + * TODO: Above sounds a little arbitrary. On the other hand, there is no object referenced by {@link #NULL} so we can also + * say all the objects referenced by {@link #NULL} were derived from {@link Object}. However, the Java Language's + * "instanceof" operator proves us wrong: "null" is not referring to an instance of {@link Object} :) */ } /* This code is from a bug report by Konstantin Shagin */ @@ -106,8 +106,8 @@ public abstract class ReferenceType extends Type { } } if (this instanceof ArrayType || t instanceof ArrayType) { - return Type.OBJECT; - // TODO: Is there a proof of OBJECT being the direct ancestor of every ArrayType? + return OBJECT; + // TODO: Is there a proof of {@link #OBJECT} being the direct ancestor of every ArrayType? } return getFirstCommonSuperclassInternal(t); } @@ -115,7 +115,7 @@ public abstract class ReferenceType extends Type { private ReferenceType getFirstCommonSuperclassInternal(final ReferenceType t) throws ClassNotFoundException { if (this instanceof ObjectType && ((ObjectType) this).referencesInterfaceExact() || t instanceof ObjectType && ((ObjectType) t).referencesInterfaceExact()) { - return Type.OBJECT; + return OBJECT; // TODO: The above line is correct comparing to the vmspec2. But one could // make class file verification a bit stronger here by using the notion of // superinterfaces or even castability or assignment compatibility. @@ -142,7 +142,7 @@ public abstract class ReferenceType extends Type { } } } - // Huh? Did you ask for Type.OBJECT's superclass?? + // Huh? Did you ask for OBJECT's superclass?? return null; } @@ -158,7 +158,7 @@ public abstract class ReferenceType extends Type { return false; } final ReferenceType T = (ReferenceType) t; - if (this.equals(Type.NULL)) { + if (equals(NULL)) { return true; // This is not explicitly stated, but clear. Isn't it? } /* @@ -169,7 +169,7 @@ public abstract class ReferenceType extends Type { * If T is a class type, then this must be the same class as T, or this must be a subclass of T; */ if (T instanceof ObjectType && ((ObjectType) T).referencesClassExact() - && (this.equals(T) || Repository.instanceOf(((ObjectType) this).getClassName(), ((ObjectType) T).getClassName()))) { + && (equals(T) || Repository.instanceOf(((ObjectType) this).getClassName(), ((ObjectType) T).getClassName()))) { return true; } /* @@ -187,14 +187,14 @@ public abstract class ReferenceType extends Type { /* * If T is a class type, then T must be Object (2.4.7). */ - if (T instanceof ObjectType && ((ObjectType) T).referencesClassExact() && T.equals(Type.OBJECT)) { + if (T instanceof ObjectType && ((ObjectType) T).referencesClassExact() && T.equals(OBJECT)) { return true; } /* * If T is an interface type, then T must be the same interface as this or a superinterface of this (2.13.2). */ if (T instanceof ObjectType && ((ObjectType) T).referencesInterfaceExact() - && (this.equals(T) || Repository.implementationOf(((ObjectType) this).getClassName(), ((ObjectType) T).getClassName()))) { + && (equals(T) || Repository.implementationOf(((ObjectType) this).getClassName(), ((ObjectType) T).getClassName()))) { return true; } } @@ -205,7 +205,7 @@ public abstract class ReferenceType extends Type { /* * If T is a class type, then T must be Object (2.4.7). */ - if (T instanceof ObjectType && ((ObjectType) T).referencesClassExact() && T.equals(Type.OBJECT)) { + if (T instanceof ObjectType && ((ObjectType) T).referencesClassExact() && T.equals(OBJECT)) { return true; } /* @@ -246,14 +246,14 @@ public abstract class ReferenceType extends Type { /** * Return true iff this type is castable to another type t as defined in the JVM specification. The case where this is - * Type.NULL is not defined (see the CHECKCAST definition in the JVM specification). However, because e.g. CHECKCAST + * {@link #NULL} is not defined (see the CHECKCAST definition in the JVM specification). However, because e.g. CHECKCAST * doesn't throw a ClassCastException when casting a null reference to any Object, true is returned in this case. * * @throws ClassNotFoundException if any classes or interfaces required to determine assignment compatibility can't be * found */ public boolean isCastableTo(final Type t) throws ClassNotFoundException { - if (this.equals(Type.NULL)) { + if (equals(NULL)) { return t instanceof ReferenceType; // If this is ever changed in isAssignmentCompatible() } return isAssignmentCompatibleWith(t); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SWITCH.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SWITCH.java index aed1626ec0d..f929176c174 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SWITCH.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SWITCH.java @@ -95,7 +95,7 @@ public final class SWITCH implements CompoundInstruction { * @param maxGap maximum gap that may between case branches */ public SWITCH(final int[] match, final InstructionHandle[] targets, final InstructionHandle target, final int maxGap) { - int[] matchClone = match.clone(); + final int[] matchClone = match.clone(); final InstructionHandle[] targetsClone = targets.clone(); final int matchLength = match.length; if (matchLength < 2) { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Select.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Select.java index a90e795e99f..a3086ac1664 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Select.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Select.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -33,7 +33,7 @@ import com.sun.org.apache.bcel.internal.util.ByteSequence; * @see LOOKUPSWITCH * @see TABLESWITCH * @see InstructionList - * @LastModified: May 2021 + * @LastModified: Sept 2025 */ public abstract class Select extends BranchInstruction implements VariableLengthInstruction, StackConsumer /* @since 6.0 */, StackProducer { @@ -87,7 +87,7 @@ public abstract class Select extends BranchInstruction implements VariableLength * @param defaultTarget default instruction target */ Select(final short opcode, final int[] match, final InstructionHandle[] targets, final InstructionHandle defaultTarget) { - // don't set default target before instuction is built + // don't set default target before instruction is built super(opcode, null); this.match = match; this.targets = targets; @@ -288,7 +288,7 @@ public abstract class Select extends BranchInstruction implements VariableLength } /** - * Set branch target for 'i'th case + * Sets branch target for 'i'th case */ public void setTarget(final int i, final InstructionHandle target) { // TODO could be package-protected? notifyTarget(targets[i], target, this); @@ -314,7 +314,11 @@ public abstract class Select extends BranchInstruction implements VariableLength for (int i = 0; i < match_length; i++) { String s = "null"; if (targets[i] != null) { - s = targets[i].getInstruction().toString(); + if (targets[i].getInstruction() == this) { + s = ""; + } else { + s = targets[i].getInstruction().toString(); + } } buf.append("(").append(match[i]).append(", ").append(s).append(" = {").append(indices[i]).append("})"); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SimpleElementValueGen.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SimpleElementValueGen.java index a4de20315d7..363b3237632 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SimpleElementValueGen.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/SimpleElementValueGen.java @@ -166,7 +166,7 @@ public class SimpleElementValueGen extends ElementValueGen { dos.writeShort(idx); break; default: - throw new IllegalStateException("SimpleElementValueGen doesnt know how to write out type " + super.getElementValueType()); + throw new IllegalStateException("SimpleElementValueGen doesn't know how to write out type " + super.getElementValueType()); } } @@ -184,7 +184,7 @@ public class SimpleElementValueGen extends ElementValueGen { public int getValueInt() { if (super.getElementValueType() != PRIMITIVE_INT) { - throw new IllegalStateException("Dont call getValueString() on a non STRING ElementValue"); + throw new IllegalStateException("Don't call getValueString() on a non STRING ElementValue"); } final ConstantInteger c = (ConstantInteger) getConstantPool().getConstant(idx); return c.getBytes(); @@ -192,7 +192,7 @@ public class SimpleElementValueGen extends ElementValueGen { public String getValueString() { if (super.getElementValueType() != STRING) { - throw new IllegalStateException("Dont call getValueString() on a non STRING ElementValue"); + throw new IllegalStateException("Don't call getValueString() on a non STRING ElementValue"); } final ConstantUtf8 c = (ConstantUtf8) getConstantPool().getConstant(idx); return c.getBytes(); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TargetLostException.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TargetLostException.java index 40ed6ff4c38..038bbe63148 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TargetLostException.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TargetLostException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -21,32 +21,32 @@ package com.sun.org.apache.bcel.internal.generic; /** - * Thrown by InstructionList.remove() when one or multiple disposed instructions are still being referenced by an - * InstructionTargeter object. I.e. the InstructionTargeter has to be notified that (one of) the InstructionHandle it is - * referencing is being removed from the InstructionList and thus not valid anymore. + * Thrown by {@link InstructionList} when one or multiple disposed instructions are still being referenced by an {@link InstructionTargeter} object. I.e. the + * {@link InstructionTargeter} has to be notified that (one of) the {@link InstructionHandle} it is referencing is being removed from the + * {@link InstructionList} and thus not valid anymore. * *

- * Making this an exception instead of a return value forces the user to handle these case explicitly in a try { ... } - * catch. The following code illustrates how this may be done: + * Making this an exception instead of a return value forces the user to handle these case explicitly in a try { ... } catch. The following code illustrates how + * this may be done: *

* - *
+ * 
  *     ...
  *     try {
  *         il.delete(start_ih, end_ih);
- *     } catch(TargetLostException e) {
+ *     } catch (TargetLostException e) {
  *         for (InstructionHandle target : e.getTargets()) {
  *             for (InstructionTargeter targeter : target.getTargeters()) {
  *                 targeter.updateTarget(target, new_target);
  *             }
  *         }
  *     }
- * 
+ *
* * @see InstructionHandle * @see InstructionList * @see InstructionTargeter - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public final class TargetLostException extends Exception { @@ -54,12 +54,14 @@ public final class TargetLostException extends Exception { @SuppressWarnings("serial") // Array component type is not Serializable private final InstructionHandle[] targets; - TargetLostException(final InstructionHandle[] t, final String mesg) { - super(mesg); - targets = t; + TargetLostException(final InstructionHandle[] targets, final String message) { + super(message); + this.targets = targets; } /** + * Gets the list of instructions still being targeted. + * * @return list of instructions still being targeted. */ public InstructionHandle[] getTargets() { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Type.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Type.java index ea20710af2e..b58645b402e 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Type.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/Type.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -26,12 +26,14 @@ import java.util.Objects; import com.sun.org.apache.bcel.internal.Const; import com.sun.org.apache.bcel.internal.classfile.ClassFormatException; +import com.sun.org.apache.bcel.internal.classfile.InvalidMethodSignatureException; import com.sun.org.apache.bcel.internal.classfile.Utility; +import jdk.xml.internal.Utils; /** - * Abstract super class for all possible java types, namely basic types such as int, object types like String and array + * Abstract super class for all possible Java types, namely basic types such as int, object types like String and array * types, e.g. int[] - * @LastModified: May 2021 + * @LastModified: Sept 2025 */ public abstract class Type { @@ -88,15 +90,15 @@ public abstract class Type { // Skip any type arguments to read argument declarations between '(' and ')' index = signature.indexOf('(') + 1; if (index <= 0) { - throw new ClassFormatException("Invalid method signature: " + signature); + throw new InvalidMethodSignatureException(signature); } while (signature.charAt(index) != ')') { vec.add(getType(signature.substring(index))); - // corrected concurrent private static field acess + // corrected concurrent private static field access index += unwrap(CONSUMED_CHARS); // update position } } catch (final StringIndexOutOfBoundsException e) { // Should never occur - throw new ClassFormatException("Invalid method signature: " + signature, e); + throw new InvalidMethodSignatureException(signature, e); } final Type[] types = new Type[vec.size()]; vec.toArray(types); @@ -110,7 +112,7 @@ public abstract class Type { // Skip any type arguments to read argument declarations between '(' and ')' index = signature.indexOf('(') + 1; if (index <= 0) { - throw new ClassFormatException("Invalid method signature: " + signature); + throw new InvalidMethodSignatureException(signature); } while (signature.charAt(index) != ')') { final int coded = getTypeSize(signature.substring(index)); @@ -118,7 +120,7 @@ public abstract class Type { index += consumed(coded); } } catch (final StringIndexOutOfBoundsException e) { // Should never occur - throw new ClassFormatException("Invalid method signature: " + signature, e); + throw new InvalidMethodSignatureException(signature, e); } return res; } @@ -154,13 +156,13 @@ public abstract class Type { final int index = signature.lastIndexOf(')') + 1; return getType(signature.substring(index)); } catch (final StringIndexOutOfBoundsException e) { // Should never occur - throw new ClassFormatException("Invalid method signature: " + signature, e); + throw new InvalidMethodSignatureException(signature, e); } } static int getReturnTypeSize(final String signature) { final int index = signature.lastIndexOf(')') + 1; - return Type.size(getTypeSize(signature.substring(index))); + return size(getTypeSize(signature.substring(index))); } public static String getSignature(final java.lang.reflect.Method meth) { @@ -175,7 +177,7 @@ public abstract class Type { } /** - * Convert runtime java.lang.Class to BCEL Type object. + * Convert runtime {@link Class} to BCEL Type object. * * @param cls Java class * @return corresponding Type object @@ -183,7 +185,7 @@ public abstract class Type { public static Type getType(final Class cls) { Objects.requireNonNull(cls, "cls"); /* - * That's an amzingly easy case, because getName() returns the signature. That's what we would have liked anyway. + * That's an amazingly easy case, because getName() returns the signature. That's what we would have liked anyway. */ if (cls.isArray()) { return getType(cls.getName()); @@ -230,7 +232,7 @@ public abstract class Type { public static Type getType(final String signature) throws StringIndexOutOfBoundsException { final byte type = Utility.typeOfSignature(signature); if (type <= Const.T_VOID) { - // corrected concurrent private static field acess + // corrected concurrent private static field access wrap(CONSUMED_CHARS, 1); return BasicType.getType(type); } @@ -246,7 +248,7 @@ public abstract class Type { } while (signature.charAt(dim) == '['); // Recurse, but just once, if the signature is ok final Type t = getType(signature.substring(dim)); - // corrected concurrent private static field acess + // corrected concurrent private static field access // consumed_chars += dim; // update counter - is replaced by final int temp = unwrap(CONSUMED_CHARS) + dim; wrap(CONSUMED_CHARS, temp); @@ -254,7 +256,7 @@ public abstract class Type { } /** - * Convert runtime java.lang.Class[] to BCEL Type objects. + * Convert runtime {@code java.lang.Class[]} to BCEL Type objects. * * @param classes an array of runtime class objects * @return array of corresponding Type objects @@ -286,6 +288,24 @@ public abstract class Type { return encode(1, index + 1); } + static String internalTypeNameToSignature(final String internalTypeName) { + if (Utils.isEmpty(internalTypeName) || Arrays.asList(Const.SHORT_TYPE_NAMES).contains(internalTypeName)) { + return internalTypeName; + } + switch (internalTypeName.charAt(0)) { + case '[': + return internalTypeName; + case 'L': + case 'T': + if (internalTypeName.charAt(internalTypeName.length() - 1) == ';') { + return internalTypeName; + } + return 'L' + internalTypeName + ';'; + default: + return 'L' + internalTypeName + ';'; + } + } + static int size(final int coded) { return coded & 3; } @@ -361,7 +381,7 @@ public abstract class Type { } /** - * @return hashcode of Type + * @return hash code of Type */ @Override public int hashCode() { @@ -369,31 +389,23 @@ public abstract class Type { } /** - * boolean, short and char variable are considered as int in the stack or local variable area. Returns {@link Type#INT} - * for {@link Type#BOOLEAN}, {@link Type#SHORT} or {@link Type#CHAR}, otherwise returns the given type. + * boolean, short and char variable are considered as int in the stack or local variable area. Returns {@link #INT} + * for {@link #BOOLEAN}, {@link #SHORT} or {@link #CHAR}, otherwise returns the given type. * * @since 6.0 */ public Type normalizeForStackOrLocal() { - if (this == Type.BOOLEAN || this == Type.BYTE || this == Type.SHORT || this == Type.CHAR) { - return Type.INT; + if (this == BOOLEAN || this == BYTE || this == SHORT || this == CHAR) { + return INT; } return this; } - /* - * Currently only used by the ArrayType constructor. The signature has a complicated dependency on other parameter so - * it's tricky to do it in a call to the super ctor. - */ - void setSignature(final String signature) { - this.signature = signature; - } - /** * @return Type string, e.g. 'int[]' */ @Override public String toString() { - return this.equals(Type.NULL) || type >= Const.T_UNKNOWN ? signature : Utility.signatureToString(signature, false); + return equals(NULL) || type >= Const.T_UNKNOWN ? signature : Utility.signatureToString(signature, false); } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TypedInstruction.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TypedInstruction.java index 5a22942a6a7..27b952f3996 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TypedInstruction.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/TypedInstruction.java @@ -22,7 +22,7 @@ package com.sun.org.apache.bcel.internal.generic; /** - * Get the type associated with an instruction, int for ILOAD, or the type of the field of a PUTFIELD instruction, e.g.. + * Gets the type associated with an instruction, int for ILOAD, or the type of the field of a PUTFIELD instruction, e.g.. */ public interface TypedInstruction { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/package-info.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/package-info.java new file mode 100644 index 00000000000..63d4dc876ce --- /dev/null +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/generic/package-info.java @@ -0,0 +1,26 @@ +/* + * reserved comment block + * DO NOT REMOVE OR ALTER! + */ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Generic part of the Apache Byte Code Engineering Library (BCEL), classes to dynamically modify class objects + * and byte code instructions. + */ +package com.sun.org.apache.bcel.internal.generic; diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/package-info.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/package-info.java new file mode 100644 index 00000000000..581037d7981 --- /dev/null +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/package-info.java @@ -0,0 +1,26 @@ +/* + * reserved comment block + * DO NOT REMOVE OR ALTER! + */ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Basic classes for the Apache Byte Code Engineering Library (BCEL) and constants defined by the + * JVM specification. + */ +package com.sun.org.apache.bcel.internal; diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELComparator.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELComparator.java index 2e663bfdaa1..fb32dc35e0b 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELComparator.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELComparator.java @@ -22,26 +22,27 @@ package com.sun.org.apache.bcel.internal.util; /** - * Used for BCEL comparison strategy + * Used for BCEL comparison strategy. * + * @param What type we are comparing. * @since 5.2 */ -public interface BCELComparator { +public interface BCELComparator { /** - * Compare two objects and return what THIS.equals(THAT) should return + * Compares two objects and return what a.equals(b) should return. * - * @param THIS - * @param THAT - * @return true if and only if THIS equals THAT + * @param a an object. + * @param b an object to be compared with {@code a} for equality. + * @return {@code true} if the arguments are equal to each other and {@code false} otherwise. */ - boolean equals(Object THIS, Object THAT); + boolean equals(T a, T b); /** - * Return hashcode for THIS.hashCode() + * Gets the hash code for o.hashCode() * - * @param THIS - * @return hashcode for THIS.hashCode() + * @param o + * @return hash code for o.hashCode() */ - int hashCode(Object THIS); + int hashCode(T o); } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELFactory.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELFactory.java index c931fb1e422..93f22e7d0ad 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELFactory.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -63,9 +63,9 @@ import com.sun.org.apache.bcel.internal.generic.Type; * Factory creates il.append() statements, and sets instruction targets. A helper class for BCELifier. * * @see BCELifier - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ -class BCELFactory extends EmptyVisitor { +final class BCELFactory extends EmptyVisitor { private static final String CONSTANT_PREFIX = Const.class.getSimpleName() + "."; private final MethodGen methodGen; @@ -88,7 +88,7 @@ class BCELFactory extends EmptyVisitor { if (value instanceof String) { embed = '"' + Utility.convertString(embed) + '"'; } else if (value instanceof Character) { - embed = "(char)0x" + Integer.toHexString(((Character) value).charValue()); + embed = "(char) 0x" + Integer.toHexString(((Character) value).charValue()); } else if (value instanceof Float) { final Float f = (Float) value; if (Float.isNaN(f)) { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELifier.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELifier.java index 151083ea71b..0eb9bfb4ee1 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELifier.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/BCELifier.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -30,11 +30,15 @@ import java.util.Locale; import com.sun.org.apache.bcel.internal.Const; import com.sun.org.apache.bcel.internal.Repository; import com.sun.org.apache.bcel.internal.classfile.ClassParser; +import com.sun.org.apache.bcel.internal.classfile.Code; import com.sun.org.apache.bcel.internal.classfile.ConstantValue; import com.sun.org.apache.bcel.internal.classfile.ExceptionTable; import com.sun.org.apache.bcel.internal.classfile.Field; import com.sun.org.apache.bcel.internal.classfile.JavaClass; import com.sun.org.apache.bcel.internal.classfile.Method; +import com.sun.org.apache.bcel.internal.classfile.StackMap; +import com.sun.org.apache.bcel.internal.classfile.StackMapEntry; +import com.sun.org.apache.bcel.internal.classfile.StackMapType; import com.sun.org.apache.bcel.internal.classfile.Utility; import com.sun.org.apache.bcel.internal.generic.ArrayType; import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; @@ -46,7 +50,7 @@ import com.sun.org.apache.bcel.internal.generic.Type; * This gives new users of BCEL a useful example showing how things are done with BCEL. It does not cover all features * of BCEL, but tries to mimic hand-written code as close as possible. * - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public class BCELifier extends com.sun.org.apache.bcel.internal.classfile.EmptyVisitor { @@ -74,7 +78,7 @@ public class BCELifier extends com.sun.org.apache.bcel.internal.classfile.EmptyV /** * Default main method */ - public static void _main(final String[] argv) throws Exception { + public static void main(final String[] argv) throws Exception { if (argv.length != 1) { System.out.println("Usage: BCELifier className"); System.out.println("\tThe class must exist on the classpath"); @@ -311,6 +315,13 @@ public class BCELifier extends com.sun.org.apache.bcel.internal.classfile.EmptyV printWriter.println("\");"); } } + final Code code = method.getCode(); + if (code != null) { + final StackMap stackMap = code.getStackMap(); + if (stackMap != null) { + stackMap.accept(this); + } + } printWriter.println(); final BCELFactory factory = new BCELFactory(mg, printWriter); factory.start(); @@ -319,4 +330,78 @@ public class BCELifier extends com.sun.org.apache.bcel.internal.classfile.EmptyV printWriter.println(" _cg.addMethod(method.getMethod());"); printWriter.println(" il.dispose();"); } + + @Override + public void visitStackMap(final StackMap stackMap) { + super.visitStackMap(stackMap); + printWriter.print(" method.addCodeAttribute("); + printWriter.print("new StackMap(_cp.addUtf8(\""); + printWriter.print(stackMap.getName()); + printWriter.print("\"), "); + printWriter.print(stackMap.getLength()); + printWriter.print(", "); + printWriter.print("new StackMapEntry[] {"); + final StackMapEntry[] table = stackMap.getStackMap(); + for (int i = 0; i < table.length; i++) { + table[i].accept(this); + if (i < table.length - 1) { + printWriter.print(", "); + } else { + printWriter.print(" }"); + } + } + printWriter.print(", _cp.getConstantPool())"); + printWriter.println(");"); + } + + @Override + public void visitStackMapEntry(final StackMapEntry stackMapEntry) { + super.visitStackMapEntry(stackMapEntry); + printWriter.print("new StackMapEntry("); + printWriter.print(stackMapEntry.getFrameType()); + printWriter.print(", "); + printWriter.print(stackMapEntry.getByteCodeOffset()); + printWriter.print(", "); + visitStackMapTypeArray(stackMapEntry.getTypesOfLocals()); + printWriter.print(", "); + visitStackMapTypeArray(stackMapEntry.getTypesOfStackItems()); + printWriter.print(", _cp.getConstantPool())"); + } + + /** + * Visits a {@link StackMapType} object. + * @param stackMapType object to visit + * @since 6.7.1 + */ + @Override + public void visitStackMapType(final StackMapType stackMapType) { + super.visitStackMapType(stackMapType); + printWriter.print("new StackMapType((byte)"); + printWriter.print(stackMapType.getType()); + printWriter.print(", "); + if (stackMapType.hasIndex()) { + printWriter.print("_cp.addClass(\""); + printWriter.print(stackMapType.getClassName()); + printWriter.print("\")"); + } else { + printWriter.print("-1"); + } + printWriter.print(", _cp.getConstantPool())"); + } + + private void visitStackMapTypeArray(final StackMapType[] types) { + if (types == null || types.length == 0) { + printWriter.print("null"); // null translates to StackMapType.EMPTY_ARRAY + } else { + printWriter.print("new StackMapType[] {"); + for (int i = 0; i < types.length; i++) { + types[i].accept(this); + if (i < types.length - 1) { + printWriter.print(", "); + } else { + printWriter.print(" }"); + } + } + } + } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Class2HTML.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Class2HTML.java index f644c698b72..10d31974d47 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Class2HTML.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Class2HTML.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -53,7 +53,7 @@ import com.sun.org.apache.bcel.internal.classfile.Utility; * All subfiles reference each other appropriately, e.g. clicking on a method in the Method's frame will jump to the * appropriate method in the Code frame. * - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public class Class2HTML { @@ -73,7 +73,7 @@ public class Class2HTML { basicTypes.add("float"); } - public static void _main(final String[] argv) throws IOException { + public static void main(final String[] argv) throws IOException { final String[] fileName = new String[argv.length]; int files = 0; ClassParser parser = null; @@ -89,7 +89,7 @@ public class Class2HTML { if (argv[i].equals("-d")) { // Specify target directory, default '.' dir = argv[++i]; if (!dir.endsWith("" + sep)) { - dir = dir + sep; + dir += sep; } final File store = new File(dir); if (!store.isDirectory()) { @@ -115,7 +115,7 @@ public class Class2HTML { if (zipFile == null) { parser = new ClassParser(fileName[i]); // Create parser object from file } else { - parser = new ClassParser(zipFile, fileName[i]); // Create parser object from zip file + parser = new ClassParser(zipFile, fileName[i]); // Create parser object from ZIP file } javaClass = parser.parse(); new Class2HTML(javaClass, dir); diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ClassSet.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ClassSet.java index 178ccc786b1..e95e8fbd0a0 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ClassSet.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/ClassSet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -30,7 +30,7 @@ import com.sun.org.apache.bcel.internal.classfile.JavaClass; * Utility class implementing a (type-safe) set of JavaClass objects. Since JavaClass has no equals() method, the name of the class is used for comparison. * * @see ClassStack - * @LastModified: Feb 2023 + * @LastModified: Sept 2025 */ public class ClassSet { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/CodeHTML.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/CodeHTML.java index 723fc07509b..1935d724b3b 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/CodeHTML.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/CodeHTML.java @@ -542,7 +542,7 @@ final class CodeHTML { final String str = codeToHTML(stream, methodNumber); String anchor = ""; /* - * Set an anchor mark if this line is targetted by a goto, jsr, etc. Defining an anchor for every line is very + * Sets an anchor mark if this line is targetted by a goto, jsr, etc. Defining an anchor for every line is very * inefficient! */ if (gotoSet.get(offset)) { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/InstructionFinder.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/InstructionFinder.java index 5b045bf08cc..510fe4a03a6 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/InstructionFinder.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/InstructionFinder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -63,14 +63,13 @@ import com.sun.org.apache.bcel.internal.generic.InstructionList; * * @see com.sun.org.apache.bcel.internal.generic.Instruction * @see InstructionList - * @LastModified: May 2021 + * @LastModified: Sept 2025 */ public class InstructionFinder { /** * Code patterns found may be checked using an additional user-defined constraint object whether they really match the * needed criterion. I.e., check constraints that can not expressed with regular expressions. - * */ public interface CodeConstraint { @@ -374,7 +373,7 @@ public class InstructionFinder { // } // private static final String pattern2string( String pattern, boolean make_string ) { -// StringBuffer buf = new StringBuffer(); +// StringBuilder buf = new StringBuilder(); // for (int i = 0; i < pattern.length(); i++) { // char ch = pattern.charAt(i); // if (ch >= OFFSET) { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Repository.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Repository.java index 8d1ddf493cd..c44e36d0a81 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Repository.java +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/Repository.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -25,8 +25,8 @@ import com.sun.org.apache.bcel.internal.classfile.JavaClass; * Abstract definition of a class repository. Instances may be used to load classes from different sources and may be * used in the Repository.setRepository method. * - * @see org.apache.bcel.Repository - * @LastModified: Feb 2023 + * @see com.sun.org.apache.bcel.internal.Repository + * @LastModified: Sept 2025 */ public interface Repository { diff --git a/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/package-info.java b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/package-info.java new file mode 100644 index 00000000000..2bd92f155bc --- /dev/null +++ b/src/java.xml/share/classes/com/sun/org/apache/bcel/internal/util/package-info.java @@ -0,0 +1,32 @@ +/* + * reserved comment block + * DO NOT REMOVE OR ALTER! + */ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * Utility classes for the Apache Byte Code Engineering Library (BCEL), namely: + *
    + *
  • Collection classes for JavaClass objects
  • + *
  • A converter for class files to HTML
  • + *
  • A tool to find instructions patterns via regular expressions
  • + *
  • A class to find classes as defined in the CLASSPATH
  • + *
  • A class loader that allows to create classes at run time
  • + *
+ */ +package com.sun.org.apache.bcel.internal.util; diff --git a/src/java.xml/share/classes/jdk/xml/internal/Utils.java b/src/java.xml/share/classes/jdk/xml/internal/Utils.java index f55ab95a58f..96d9b1b9521 100644 --- a/src/java.xml/share/classes/jdk/xml/internal/Utils.java +++ b/src/java.xml/share/classes/jdk/xml/internal/Utils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,11 @@ package jdk.xml.internal; +import java.lang.reflect.Array; import java.util.Arrays; +import java.util.Objects; import java.util.function.Supplier; +import java.util.stream.Stream; /** * General utility. Use JdkXmlUtils for XML processing related functions. @@ -76,4 +79,59 @@ public class Utils { System.arraycopy(items, 0, result, original.length, items.length); return result; } + + /** + * Returns the original array, or an empty array if it is {@code null}. + * @param array the specified array + * @return the original array, or an empty array if it is {@code null} + */ + public static byte[] createEmptyArrayIfNull(byte[] array) { + return (array != null) ? array : new byte[0]; + } + + /** + * Returns the original array, or an empty array if it is {@code null}. + * @param array the specified array + * @return the original array, or an empty array if it is {@code null} + */ + public static int[] createEmptyArrayIfNull(int[] array) { + return (array != null) ? array : new int[0]; + } + + /** + * Returns the original array, or an empty array if it is {@code null}. + * @param the class type + * @param array the specified array + * @param type the type of the array + * @return the original array, or an empty array if it is {@code null} + */ + public static T[] createEmptyArrayIfNull(final T[] array, final Class type) { + Objects.requireNonNull(type, "The type argument should not be null."); + + return (array != null) ? array : type.cast(Array.newInstance(type.getComponentType(), 0)); + } + + /** + * Returns the new stream created by {@code Stream.of(values)} or an empty + * sequential stream created by {@code Stream.empty()} if values is null. + * + * @param the type of stream elements + * @param values the elements of the new stream + * @return the new stream created by {@code Stream.of(values)} or an empty + * sequential stream created by {@code Stream.empty()} if values is null. + */ + @SafeVarargs + @SuppressWarnings("varargs") // Creating a stream from an array is safe + public static Stream streamOfIfNonNull(final T... values) { + return values == null ? Stream.empty() : Stream.of(values); + } + + /** + * Checks if a CharSequence is empty ("") or null. + * @param cs the CharSequence to check, may be null + * @return {@code true} if the CharSequence is empty or null + */ + public static boolean isEmpty(final CharSequence cs) { + return cs == null || cs.length() == 0; + } } diff --git a/src/java.xml/share/legal/bcel.md b/src/java.xml/share/legal/bcel.md index 2c673d6b1af..b64fc3640d4 100644 --- a/src/java.xml/share/legal/bcel.md +++ b/src/java.xml/share/legal/bcel.md @@ -1,4 +1,4 @@ -## Apache Commons Byte Code Engineering Library (BCEL) Version 6.7.0 +## Apache Commons Byte Code Engineering Library (BCEL) Version 6.10.0 ### Apache Commons BCEL Notice

From ebb6fd7d7865fd20ff2f90b4ef72c5ef6a3e5dea Mon Sep 17 00:00:00 2001
From: Mikhail Yankelevich 
Date: Fri, 3 Oct 2025 07:37:17 +0000
Subject: [PATCH 0049/1639] 8360562: sun/security/tools/keytool/i18n.java add
 an ability to add comment for failures

Reviewed-by: rhalade
---
 test/jdk/sun/security/tools/keytool/i18n.java | 46 ++++++++++++++++++-
 1 file changed, 44 insertions(+), 2 deletions(-)

diff --git a/test/jdk/sun/security/tools/keytool/i18n.java b/test/jdk/sun/security/tools/keytool/i18n.java
index 6eac0239eee..ab9da8b1d3e 100644
--- a/test/jdk/sun/security/tools/keytool/i18n.java
+++ b/test/jdk/sun/security/tools/keytool/i18n.java
@@ -63,11 +63,21 @@
 
 import jdk.test.lib.UIBuilder;
 
-import javax.swing.*;
+import javax.swing.JDialog;
+import javax.swing.SwingUtilities;
+import javax.swing.JTextArea;
+import javax.swing.JButton;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JFrame;
+import java.awt.FlowLayout;
+import java.awt.BorderLayout;
 import java.io.ByteArrayOutputStream;
 import java.io.PrintStream;
 import java.util.Locale;
 
+import static javax.swing.BorderFactory.createEmptyBorder;
+
 public class i18n {
     private static final String[][] TABLE = new String[][]{
             {"-help", "All the output in this test should be in ${LANG}. "
@@ -234,11 +244,12 @@ public class i18n {
                     "Output in ${LANG}. Check keytool error: java.lang"
                             + ".IllegalArgumentException: if -protected is "
                             + "specified, then -storepass, -keypass, and -new "
-                            + "must not be specified."},
+                            + "must not be specified."}
     };
     private static String TEST_SRC = System.getProperty("test.src");
     private static int TIMEOUT_MS = 120000;
     private volatile boolean failed = false;
+    private volatile String failureReason = "";
     private volatile boolean aborted = false;
     private Thread currentThread = null;
 
@@ -330,6 +341,7 @@ public class i18n {
 
             if (failed) {
                 System.out.println(command + ": TEST FAILED");
+                System.out.println("REASON: " + failureReason);
                 System.out.println(message);
             } else {
                 System.out.println(command + ": TEST PASSED");
@@ -348,6 +360,7 @@ public class i18n {
 
     public void fail() {
         failed = true;
+        failureReason = requestFailDescription();
         currentThread.interrupt();
     }
 
@@ -355,4 +368,33 @@ public class i18n {
         aborted = true;
         currentThread.interrupt();
     }
+
+    /**
+     * Opens a prompt to enter a failure reason to be filled by the tester
+     */
+     public static String requestFailDescription() {
+
+        final JDialog dialogWindow = new JDialog(new JFrame(), "Failure Description", true);
+        final JTextArea reasonTextArea = new JTextArea(5, 20);
+
+        final JButton okButton = new JButton("OK");
+        okButton.addActionListener(_ -> dialogWindow.setVisible(false));
+
+        final JPanel okayBtnPanel = new JPanel(
+                new FlowLayout(FlowLayout.CENTER, 4, 0));
+        okayBtnPanel.setBorder(createEmptyBorder(4, 0, 0, 0));
+        okayBtnPanel.add(okButton);
+
+        final JPanel mainPanel = new JPanel(new BorderLayout());
+        mainPanel.add(new JScrollPane(reasonTextArea), BorderLayout.CENTER);
+        mainPanel.add(okayBtnPanel, BorderLayout.SOUTH);
+
+        dialogWindow.add(mainPanel);
+        dialogWindow.pack();
+        dialogWindow.setVisible(true);
+
+        dialogWindow.dispose();
+
+        return reasonTextArea.getText();
+    }
 }

From 2e783963d21c8edd88e79226ca473cfe0e41335b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mar=C3=ADa=20Arias=20de=20Reyna=20Dom=C3=ADnguez?=
 
Date: Fri, 3 Oct 2025 07:57:24 +0000
Subject: [PATCH 0050/1639] 8369037: Identify owning method for MethodData and
 MethodCounters in AOT map output

Reviewed-by: iklam, asmehra, adinn, macarte
---
 src/hotspot/share/cds/aotMapLogger.cpp | 20 ++++++++++++++++++++
 src/hotspot/share/cds/aotMapLogger.hpp |  4 ++++
 2 files changed, 24 insertions(+)

diff --git a/src/hotspot/share/cds/aotMapLogger.cpp b/src/hotspot/share/cds/aotMapLogger.cpp
index a15d7f670d4..ded3f05a9b8 100644
--- a/src/hotspot/share/cds/aotMapLogger.cpp
+++ b/src/hotspot/share/cds/aotMapLogger.cpp
@@ -33,6 +33,8 @@
 #include "memory/metaspaceClosure.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/method.hpp"
+#include "oops/methodCounters.hpp"
+#include "oops/methodData.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/fieldDescriptor.inline.hpp"
 #include "runtime/globals_extension.hpp"
@@ -348,6 +350,12 @@ void AOTMapLogger::log_metaspace_objects_impl(address region_base, address regio
     case MetaspaceObj::MethodType:
       log_method((Method*)src, requested_addr, type_name, bytes, current);
       break;
+    case MetaspaceObj::MethodCountersType:
+      log_method_counters((MethodCounters*)src, requested_addr, type_name, bytes, current);
+      break;
+    case MetaspaceObj::MethodDataType:
+      log_method_data((MethodData*)src, requested_addr, type_name, bytes, current);
+      break;
     case MetaspaceObj::SymbolType:
       log_symbol((Symbol*)src, requested_addr, type_name, bytes, current);
       break;
@@ -389,6 +397,18 @@ void AOTMapLogger::log_const_method(ConstMethod* cm, address requested_addr, con
   log_debug(aot, map)(_LOG_PREFIX " %s", p2i(requested_addr), type_name, bytes,  cm->method()->external_name());
 }
 
+void AOTMapLogger::log_method_counters(MethodCounters* mc, address requested_addr, const char* type_name,
+                                      int bytes, Thread* current) {
+  ResourceMark rm(current);
+  log_debug(aot, map)(_LOG_PREFIX " %s", p2i(requested_addr), type_name, bytes,  mc->method()->external_name());
+}
+
+void AOTMapLogger::log_method_data(MethodData* md, address requested_addr, const char* type_name,
+                                   int bytes, Thread* current) {
+  ResourceMark rm(current);
+  log_debug(aot, map)(_LOG_PREFIX " %s", p2i(requested_addr), type_name, bytes,  md->method()->external_name());
+}
+
 void AOTMapLogger::log_klass(Klass* k, address requested_addr, const char* type_name,
                              int bytes, Thread* current) {
   ResourceMark rm(current);
diff --git a/src/hotspot/share/cds/aotMapLogger.hpp b/src/hotspot/share/cds/aotMapLogger.hpp
index 9cd67fb7ff6..f2ca4c407e3 100644
--- a/src/hotspot/share/cds/aotMapLogger.hpp
+++ b/src/hotspot/share/cds/aotMapLogger.hpp
@@ -98,6 +98,10 @@ class AOTMapLogger : AllStatic {
   static void log_constant_pool_cache(ConstantPoolCache* cpc, address requested_addr,
                                       const char* type_name, int bytes, Thread* current);
   static void log_const_method(ConstMethod* cm, address requested_addr, const char* type_name, int bytes, Thread* current);
+  static void log_method_counters(MethodCounters* mc, address requested_addr, const char* type_name, int bytes,
+  Thread* current);
+  static void log_method_data(MethodData* md, address requested_addr, const char* type_name, int bytes,
+  Thread* current);
   static void log_klass(Klass* k, address requested_addr, const char* type_name, int bytes, Thread* current);
   static void log_method(Method* m, address requested_addr, const char* type_name, int bytes, Thread* current);
   static void log_symbol(Symbol* s, address requested_addr, const char* type_name, int bytes, Thread* current);

From 134b63f0e8c4093f7ad0a528d6996898ab881d5c Mon Sep 17 00:00:00 2001
From: Yuri Gaevsky 
Date: Fri, 3 Oct 2025 09:44:56 +0000
Subject: [PATCH 0051/1639] 8322174: RISC-V: C2 VectorizedHashCode RVV Version

Reviewed-by: fyang, rehn
---
 .../cpu/riscv/c2_MacroAssembler_riscv.cpp     | 147 ++++++++++++++++--
 .../cpu/riscv/c2_MacroAssembler_riscv.hpp     |   8 +-
 src/hotspot/cpu/riscv/riscv.ad                |   1 +
 src/hotspot/cpu/riscv/riscv_v.ad              |  22 +++
 .../cpu/riscv/stubDeclarations_riscv.hpp      |   3 +
 src/hotspot/cpu/riscv/stubGenerator_riscv.cpp |  22 +++
 6 files changed, 185 insertions(+), 18 deletions(-)

diff --git a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp
index 1bdb7bc2f7c..154b62db47f 100644
--- a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp
+++ b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp
@@ -1687,6 +1687,7 @@ void C2_MacroAssembler::arrays_hashcode(Register ary, Register cnt, Register res
                                         Register tmp4, Register tmp5, Register tmp6,
                                         BasicType eltype)
 {
+  assert(!UseRVV, "sanity");
   assert_different_registers(ary, cnt, result, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, t0, t1);
 
   const int elsize = arrays_hashcode_elsize(eltype);
@@ -1759,29 +1760,143 @@ void C2_MacroAssembler::arrays_hashcode(Register ary, Register cnt, Register res
   BLOCK_COMMENT("} // arrays_hashcode");
 }
 
+void C2_MacroAssembler::arrays_hashcode_v(Register ary, Register cnt, Register result,
+                                          Register tmp1, Register tmp2, Register tmp3,
+                                          BasicType eltype)
+{
+  assert(UseRVV, "sanity");
+  assert(StubRoutines::riscv::arrays_hashcode_powers_of_31() != nullptr, "sanity");
+  assert_different_registers(ary, cnt, result, tmp1, tmp2, tmp3, t0, t1);
+
+  // The MaxVectorSize should have been set by detecting RVV max vector register
+  // size when check UseRVV (i.e. MaxVectorSize == VM_Version::_initial_vector_length).
+  // Let's use T_INT as all hashCode calculations eventually deal with ints.
+  const int lmul = 2;
+  const int stride = MaxVectorSize / sizeof(jint) * lmul;
+
+  const int elsize_bytes = arrays_hashcode_elsize(eltype);
+  const int elsize_shift = exact_log2(elsize_bytes);
+
+  switch (eltype) {
+    case T_BOOLEAN: BLOCK_COMMENT("arrays_hashcode_v(unsigned byte) {"); break;
+    case T_CHAR:    BLOCK_COMMENT("arrays_hashcode_v(char) {");          break;
+    case T_BYTE:    BLOCK_COMMENT("arrays_hashcode_v(byte) {");          break;
+    case T_SHORT:   BLOCK_COMMENT("arrays_hashcode_v(short) {");         break;
+    case T_INT:     BLOCK_COMMENT("arrays_hashcode_v(int) {");           break;
+    default:
+      ShouldNotReachHere();
+  }
+
+  const Register pow31_highest = tmp1;
+  const Register ary_end       = tmp2;
+  const Register consumed      = tmp3;
+
+  const VectorRegister v_sum    = v2;
+  const VectorRegister v_src    = v4;
+  const VectorRegister v_coeffs = v6;
+  const VectorRegister v_tmp    = v8;
+
+  const address adr_pows31 = StubRoutines::riscv::arrays_hashcode_powers_of_31()
+                           + sizeof(jint);
+  Label VEC_LOOP, DONE, SCALAR_TAIL, SCALAR_TAIL_LOOP;
+
+  // NB: at this point (a) 'result' already has some value,
+  // (b) 'cnt' is not 0 or 1, see java code for details.
+
+  andi(t0, cnt, ~(stride - 1));
+  beqz(t0, SCALAR_TAIL);
+
+  la(t1, ExternalAddress(adr_pows31));
+  lw(pow31_highest, Address(t1, -1 * sizeof(jint)));
+
+  vsetvli(consumed, cnt, Assembler::e32, Assembler::m2);
+  vle32_v(v_coeffs, t1); // 31^^(stride - 1) ... 31^^0
+  vmv_v_x(v_sum, x0);
+
+  bind(VEC_LOOP);
+  arrays_hashcode_elload_v(v_src, v_tmp, ary, eltype);
+  vmul_vv(v_src, v_src, v_coeffs);
+  vmadd_vx(v_sum, pow31_highest, v_src);
+  mulw(result, result, pow31_highest);
+  shadd(ary, consumed, ary, t0, elsize_shift);
+  subw(cnt, cnt, consumed);
+  andi(t1, cnt, ~(stride - 1));
+  bnez(t1, VEC_LOOP);
+
+  vmv_s_x(v_tmp, x0);
+  vredsum_vs(v_sum, v_sum, v_tmp);
+  vmv_x_s(t0, v_sum);
+  addw(result, result, t0);
+  beqz(cnt, DONE);
+
+  bind(SCALAR_TAIL);
+  shadd(ary_end, cnt, ary, t0, elsize_shift);
+
+  bind(SCALAR_TAIL_LOOP);
+  arrays_hashcode_elload(t0, Address(ary), eltype);
+  slli(t1, result, 5);      // optimize 31 * result
+  subw(result, t1, result); // with result<<5 - result
+  addw(result, result, t0);
+  addi(ary, ary, elsize_bytes);
+  bne(ary, ary_end, SCALAR_TAIL_LOOP);
+
+  bind(DONE);
+  BLOCK_COMMENT("} // arrays_hashcode_v");
+}
+
 int C2_MacroAssembler::arrays_hashcode_elsize(BasicType eltype) {
   switch (eltype) {
-  case T_BOOLEAN: return sizeof(jboolean);
-  case T_BYTE:    return sizeof(jbyte);
-  case T_SHORT:   return sizeof(jshort);
-  case T_CHAR:    return sizeof(jchar);
-  case T_INT:     return sizeof(jint);
-  default:
-    ShouldNotReachHere();
-    return -1;
+    case T_BOOLEAN: return sizeof(jboolean);
+    case T_BYTE:    return sizeof(jbyte);
+    case T_SHORT:   return sizeof(jshort);
+    case T_CHAR:    return sizeof(jchar);
+    case T_INT:     return sizeof(jint);
+    default:
+      ShouldNotReachHere();
+      return -1;
   }
 }
 
 void C2_MacroAssembler::arrays_hashcode_elload(Register dst, Address src, BasicType eltype) {
   switch (eltype) {
-  // T_BOOLEAN used as surrogate for unsigned byte
-  case T_BOOLEAN: lbu(dst, src);   break;
-  case T_BYTE:     lb(dst, src);   break;
-  case T_SHORT:    lh(dst, src);   break;
-  case T_CHAR:    lhu(dst, src);   break;
-  case T_INT:      lw(dst, src);   break;
-  default:
-    ShouldNotReachHere();
+    // T_BOOLEAN used as surrogate for unsigned byte
+    case T_BOOLEAN: lbu(dst, src);   break;
+    case T_BYTE:     lb(dst, src);   break;
+    case T_SHORT:    lh(dst, src);   break;
+    case T_CHAR:    lhu(dst, src);   break;
+    case T_INT:      lw(dst, src);   break;
+    default:
+      ShouldNotReachHere();
+  }
+}
+
+void C2_MacroAssembler::arrays_hashcode_elload_v(VectorRegister vdst,
+                                                 VectorRegister vtmp,
+                                                 Register src,
+                                                 BasicType eltype) {
+  assert_different_registers(vdst, vtmp);
+  switch (eltype) {
+    case T_BOOLEAN:
+      vle8_v(vtmp, src);
+      vzext_vf4(vdst, vtmp);
+      break;
+    case T_BYTE:
+      vle8_v(vtmp, src);
+      vsext_vf4(vdst, vtmp);
+      break;
+    case T_CHAR:
+      vle16_v(vtmp, src);
+      vzext_vf2(vdst, vtmp);
+      break;
+    case T_SHORT:
+      vle16_v(vtmp, src);
+      vsext_vf2(vdst, vtmp);
+      break;
+    case T_INT:
+      vle32_v(vdst, src);
+      break;
+    default:
+      ShouldNotReachHere();
   }
 }
 
diff --git a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp
index 309ef8d9d5e..2d5339dc153 100644
--- a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp
+++ b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp
@@ -92,11 +92,15 @@
                        Register tmp3, Register tmp4,
                        Register tmp5, Register tmp6,
                        BasicType eltype);
-
-  // helper function for arrays_hashcode
   int arrays_hashcode_elsize(BasicType eltype);
   void arrays_hashcode_elload(Register dst, Address src, BasicType eltype);
 
+  void arrays_hashcode_v(Register ary, Register cnt, Register result,
+                         Register tmp1, Register tmp2, Register tmp3,
+                         BasicType eltype);
+  void arrays_hashcode_elload_v(VectorRegister vdst, VectorRegister vtmp,
+                                Register src, BasicType eltype);
+
   void string_equals(Register r1, Register r2,
                      Register result, Register cnt1);
 
diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad
index 1f14c499c34..009acd628a0 100644
--- a/src/hotspot/cpu/riscv/riscv.ad
+++ b/src/hotspot/cpu/riscv/riscv.ad
@@ -10991,6 +10991,7 @@ instruct arrays_hashcode(iRegP_R11 ary, iRegI_R12 cnt, iRegI_R10 result, immI ba
                          iRegLNoSp tmp3, iRegLNoSp tmp4,
                          iRegLNoSp tmp5, iRegLNoSp tmp6, rFlagsReg cr)
 %{
+  predicate(!UseRVV);
   match(Set result (VectorizedHashCode (Binary ary cnt) (Binary result basic_type)));
   effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, TEMP tmp6,
          USE_KILL ary, USE_KILL cnt, USE basic_type, KILL cr);
diff --git a/src/hotspot/cpu/riscv/riscv_v.ad b/src/hotspot/cpu/riscv/riscv_v.ad
index f2845ee2a6c..fe323474d60 100644
--- a/src/hotspot/cpu/riscv/riscv_v.ad
+++ b/src/hotspot/cpu/riscv/riscv_v.ad
@@ -4080,6 +4080,28 @@ instruct varray_equalsC(iRegP_R11 ary1, iRegP_R12 ary2, iRegI_R10 result,
   ins_pipe(pipe_class_memory);
 %}
 
+// fast ArraysSupport.vectorizedHashCode
+instruct varrays_hashcode(iRegP_R11 ary, iRegI_R12 cnt, iRegI_R10 result, immI basic_type,
+                          vReg_V2 v2, vReg_V3 v3, vReg_V4 v4, vReg_V5 v5,
+                          vReg_V6 v6, vReg_V7 v7, vReg_V8 v8, vReg_V9 v9,
+                          iRegLNoSp tmp1, iRegLNoSp tmp2, iRegLNoSp tmp3,
+                          rFlagsReg cr)
+%{
+  predicate(UseRVV);
+  match(Set result (VectorizedHashCode (Binary ary cnt) (Binary result basic_type)));
+  effect(USE_KILL ary, USE_KILL cnt, USE basic_type,
+         TEMP v2, TEMP v3, TEMP v4, TEMP v5, TEMP v6, TEMP v7, TEMP v8, TEMP v9,
+         TEMP tmp1, TEMP tmp2, TEMP tmp3, KILL cr);
+
+  format %{ "Array HashCode array[] $ary,$cnt,$result,$basic_type -> $result   // KILL all" %}
+  ins_encode %{
+    __ arrays_hashcode_v($ary$$Register, $cnt$$Register, $result$$Register,
+                         $tmp1$$Register, $tmp2$$Register, $tmp3$$Register,
+                         (BasicType)$basic_type$$constant);
+  %}
+  ins_pipe(pipe_class_memory);
+%}
+
 instruct vstring_compareU_128b(iRegP_R11 str1, iRegI_R12 cnt1, iRegP_R13 str2, iRegI_R14 cnt2,
                           iRegI_R10 result, vReg_V4 v4, vReg_V5 v5, vReg_V6 v6, vReg_V7 v7,
                           vReg_V8 v8, vReg_V9 v9, vReg_V10 v10, vReg_V11 v11,
diff --git a/src/hotspot/cpu/riscv/stubDeclarations_riscv.hpp b/src/hotspot/cpu/riscv/stubDeclarations_riscv.hpp
index fe7f52884fa..f977d759d20 100644
--- a/src/hotspot/cpu/riscv/stubDeclarations_riscv.hpp
+++ b/src/hotspot/cpu/riscv/stubDeclarations_riscv.hpp
@@ -73,6 +73,9 @@
   do_stub(compiler, string_indexof_linear_ul)                           \
   do_arch_entry(riscv, compiler, string_indexof_linear_ul,              \
                 string_indexof_linear_ul, string_indexof_linear_ul)     \
+  do_stub(compiler, arrays_hashcode_powers_of_31)                       \
+  do_arch_entry(riscv, compiler, arrays_hashcode_powers_of_31,          \
+            arrays_hashcode_powers_of_31, arrays_hashcode_powers_of_31) \
 
 
 #define STUBGEN_FINAL_BLOBS_ARCH_DO(do_stub,                            \
diff --git a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp
index 88961ccd5a4..ec268d9bb65 100644
--- a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp
+++ b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp
@@ -6624,6 +6624,24 @@ static const int64_t right_3_bits = right_n_bits(3);
     return start;
   }
 
+  address generate_arrays_hashcode_powers_of_31() {
+    assert(UseRVV, "sanity");
+    const int lmul = 2;
+    const int stride = MaxVectorSize / sizeof(jint) * lmul;
+    __ align(CodeEntryAlignment);
+    StubCodeMark mark(this, "StubRoutines", "arrays_hashcode_powers_of_31");
+    address start = __ pc();
+    for (int i = stride; i >= 0; i--) {
+        jint power_of_31 = 1;
+        for (int j = i; j > 0; j--) {
+          power_of_31 = java_multiply(power_of_31, 31);
+        }
+        __ emit_int32(power_of_31);
+    }
+
+    return start;
+  }
+
 #endif // COMPILER2
 
   /**
@@ -6818,6 +6836,10 @@ static const int64_t right_3_bits = right_n_bits(3);
       StubRoutines::_bigIntegerRightShiftWorker = generate_bigIntegerRightShift();
     }
 
+    if (UseVectorizedHashCodeIntrinsic && UseRVV) {
+      StubRoutines::riscv::_arrays_hashcode_powers_of_31 = generate_arrays_hashcode_powers_of_31();
+    }
+
     if (UseSHA256Intrinsics) {
       Sha2Generator sha2(_masm, this);
       StubRoutines::_sha256_implCompress   = sha2.generate_sha256_implCompress(StubId::stubgen_sha256_implCompress_id);

From 72319167543a28295276f11178c17bef6680c32f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Beno=C3=AEt=20Maillard?= 
Date: Fri, 3 Oct 2025 10:40:50 +0000
Subject: [PATCH 0052/1639] 8364757: Missing Store nodes caused by bad wiring
 in PhaseIdealLoop::insert_post_loop

Reviewed-by: mhaessig, roland
---
 src/hotspot/share/opto/loopTransform.cpp      |  44 ++++++
 src/hotspot/share/opto/loopnode.hpp           |   3 +
 .../MissingStoreAfterOuterStripMinedLoop.java | 136 ++++++++++++++++++
 3 files changed, 183 insertions(+)
 create mode 100644 test/hotspot/jtreg/compiler/loopstripmining/MissingStoreAfterOuterStripMinedLoop.java

diff --git a/src/hotspot/share/opto/loopTransform.cpp b/src/hotspot/share/opto/loopTransform.cpp
index 5f5e0520e7e..f92833e9e1c 100644
--- a/src/hotspot/share/opto/loopTransform.cpp
+++ b/src/hotspot/share/opto/loopTransform.cpp
@@ -1668,6 +1668,30 @@ void PhaseIdealLoop::insert_vector_post_loop(IdealLoopTree *loop, Node_List &old
   loop->record_for_igvn();
 }
 
+Node* PhaseIdealLoop::find_last_store_in_outer_loop(Node* store, const IdealLoopTree* outer_loop) {
+  assert(store != nullptr && store->is_Store(), "starting point should be a store node");
+  // Follow the memory uses until we get out of the loop.
+  // Store nodes in the outer loop body were moved by PhaseIdealLoop::try_move_store_after_loop.
+  // Because of the conditions in try_move_store_after_loop (no other usage in the loop body
+  // except for the phi node associated with the loop head), we have the guarantee of a
+  // linear memory subgraph within the outer loop body.
+  Node* last = store;
+  Node* unique_next = store;
+  do {
+    last = unique_next;
+    for (DUIterator_Fast imax, l = last->fast_outs(imax); l < imax; l++) {
+      Node* use = last->fast_out(l);
+      if (use->is_Store() && use->in(MemNode::Memory) == last) {
+        if (is_member(outer_loop, get_ctrl(use))) {
+          assert(unique_next == last, "memory node should only have one usage in the loop body");
+          unique_next = use;
+        }
+      }
+    }
+  } while (last != unique_next);
+  return last;
+}
+
 //------------------------------insert_post_loop-------------------------------
 // Insert post loops.  Add a post loop to the given loop passed.
 Node *PhaseIdealLoop::insert_post_loop(IdealLoopTree* loop, Node_List& old_new,
@@ -1758,6 +1782,26 @@ Node *PhaseIdealLoop::insert_post_loop(IdealLoopTree* loop, Node_List& old_new,
       cur_phi->set_req(LoopNode::EntryControl, fallnew);
     }
   }
+  // Store nodes that were moved to the outer loop by PhaseIdealLoop::try_move_store_after_loop
+  // do not have an associated Phi node. Such nodes are attached to the false projection of the CountedLoopEnd node,
+  // right after the execution of the inner CountedLoop.
+  // We have to make sure that such stores in the post loop have the right memory inputs from the main loop
+  // The moved store node is always attached right after the inner loop exit, and just before the safepoint
+  const Node* if_false = main_end->proj_out(false);
+  for (DUIterator j = if_false->outs(); if_false->has_out(j); j++) {
+    Node* store = if_false->out(j);
+    if (store->is_Store()) {
+      // We only make changes if the memory input of the store is outside the outer loop body,
+      // as this is when we would normally expect a Phi as input. If the memory input
+      // is in the loop body as well, then we can safely assume it is still correct as the entire
+      // body was cloned as a unit
+      if (!is_member(outer_loop, get_ctrl(store->in(MemNode::Memory)))) {
+        Node* mem_out = find_last_store_in_outer_loop(store, outer_loop);
+        Node* store_new = old_new[store->_idx];
+        store_new->set_req(MemNode::Memory, mem_out);
+      }
+    }
+  }
 
   DEBUG_ONLY(ensure_zero_trip_guard_proj(post_head->in(LoopNode::EntryControl), false);)
   initialize_assertion_predicates_for_post_loop(main_head, post_head, first_node_index_in_cloned_loop_body);
diff --git a/src/hotspot/share/opto/loopnode.hpp b/src/hotspot/share/opto/loopnode.hpp
index bdccffa18b2..2645df86d96 100644
--- a/src/hotspot/share/opto/loopnode.hpp
+++ b/src/hotspot/share/opto/loopnode.hpp
@@ -1380,6 +1380,9 @@ public:
   // during RCE, unrolling and aligning loops.
   void insert_pre_post_loops( IdealLoopTree *loop, Node_List &old_new, bool peel_only );
 
+  // Find the last store in the body of an OuterStripMinedLoop when following memory uses
+  Node *find_last_store_in_outer_loop(Node* store, const IdealLoopTree* outer_loop);
+
   // Add post loop after the given loop.
   Node *insert_post_loop(IdealLoopTree* loop, Node_List& old_new,
                          CountedLoopNode* main_head, CountedLoopEndNode* main_end,
diff --git a/test/hotspot/jtreg/compiler/loopstripmining/MissingStoreAfterOuterStripMinedLoop.java b/test/hotspot/jtreg/compiler/loopstripmining/MissingStoreAfterOuterStripMinedLoop.java
new file mode 100644
index 00000000000..8fa6cae12e6
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/loopstripmining/MissingStoreAfterOuterStripMinedLoop.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/**
+ * @test
+ * @bug 8364757
+ * @summary Moving Store nodes from the main CountedLoop to the OuterStripMinedLoop causes
+ *          subsequent Store nodes to be eventually removed because of missing Phi nodes,
+ *          leading to wrong results.
+ *
+ * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation
+ *      -Xcomp -XX:-UseLoopPredicate -XX:-UseAutoVectorizationPredicate
+ *      -XX:CompileCommand=compileonly,compiler.loopstripmining.MissingStoreAfterOuterStripMinedLoop::test*
+ *      compiler.loopstripmining.MissingStoreAfterOuterStripMinedLoop
+ * @run main compiler.loopstripmining.MissingStoreAfterOuterStripMinedLoop
+ *
+ */
+
+package compiler.loopstripmining;
+
+public class MissingStoreAfterOuterStripMinedLoop {
+    public static int x = 0;
+    public static int y = 0;
+
+    static class A {
+        int field;
+    }
+
+    // The store node in the loop body is moved to the OuterStripLoop.
+    // When making the post loop the new store node
+    // should have the moved store node as memory input, and not the
+    // initial x = 0 store.
+    //
+    // store (x = 0)
+    //  |
+    // store (x += 1, exit of CountedLoop main)
+    //  | <-- additional rewiring due to absence of phi node
+    // store (x += 1, exit of CountedLoop post)
+    //  |
+    // store (x = 0)
+    static public void test1() {
+        x = 0;
+        for (int i = 0; i < 20000; i++) {
+            x += i;
+        }
+        x = 0;
+    }
+
+    // Two independent stores
+    // They should be wired independently in the post loop, no aliasing
+    static public void test2() {
+        x = 0;
+        y = 0;
+        for (int i = 0; i < 20000; i++) {
+            x += i;
+            y += i;
+        }
+        x = 0;
+        y = 0;
+    }
+
+    // Chain of stores with potential aliasing.
+    // The entire chain is moved to the OuterStripLoop, between the
+    // inner loop exit and the safepoint.
+    // The chain should be preserved when cloning the main loop body
+    // to create the post loop. Only the first store of the post loop
+    // should be rewired to have the last store of the main loop
+    // as memory input.
+    //
+    // ...
+    //  |
+    // store (a1.field = v, exit of CountedLoop main)
+    //  |
+    // store (a2.field = v, exit of CountedLoop main)
+    //  |
+    // store (a3.field = v, exit of CountedLoop main)
+    //  | <-- only additional rewiring needed
+    // store (a1.field = v, exit of CountedLoop post)
+    //  |
+    // store (a2.field = v, exit of CountedLoop post)
+    //  |
+    // store (a3.field = v, exit of CountedLoop post)
+    static public void test3(A a1, A a2, A a3) {
+        a1.field = 0;
+        a2.field = 0;
+        a3.field = 0;
+        int v = 0;
+        for (int i = 0; i < 20000; i++) {
+            v++;
+            a1.field = v;
+            a2.field = v;
+            a3.field = v;
+        }
+    }
+
+    public static void main(String[] strArr) {
+        A a1 = new A();
+        A a2 = new A();
+        A a3 = new A();
+
+        test1();
+        if (x != 0) {
+            throw new RuntimeException("unexpected value: " + x);
+        }
+
+        test2();
+        if (x != 0 || y != 0) {
+            throw new RuntimeException("unexpected value: " + x + " " + y);
+        }
+
+        test3(a1, a2, a3);
+        if (a1.field != 20000 || a2.field != 20000 || a3.field != 20000) {
+            throw new RuntimeException("unexpected value: " + a1.field + " " + a2.field + " " + a3.field);
+        }
+    }
+}
\ No newline at end of file

From f81c7c592bbc9f5575ed41e41d12f54cbfc5e4aa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Hannes=20Walln=C3=B6fer?= 
Date: Fri, 3 Oct 2025 15:53:37 +0000
Subject: [PATCH 0053/1639] 8276966: Improve diagnostic output for the
 mismatching parts of a hybrid snippet

Reviewed-by: prappo
---
 .../formats/html/taglets/SnippetTaglet.java    |  1 +
 .../doclet/testSnippetTag/TestSnippetTag.java  | 18 ++++++++++++++----
 2 files changed, 15 insertions(+), 4 deletions(-)

diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/SnippetTaglet.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/SnippetTaglet.java
index 32bcab0eef5..d16c47dd59f 100644
--- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/SnippetTaglet.java
+++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/SnippetTaglet.java
@@ -462,6 +462,7 @@ public class SnippetTaglet extends BaseTaglet {
                %s
                ----------------- external -----------------
                %s
+               --------------------------------------------
                """.formatted(inline, external);
     }
 
diff --git a/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetTag.java b/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetTag.java
index 413de03d23b..26030629738 100644
--- a/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetTag.java
+++ b/test/langtools/jdk/javadoc/doclet/testSnippetTag/TestSnippetTag.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8266666 8275788 8276964 8299080
+ * @bug 8266666 8275788 8276964 8299080 8276966
  * @summary Implementation for snippets
  * @library /tools/lib ../../lib
  * @modules jdk.compiler/com.sun.tools.javac.api
@@ -2166,6 +2166,7 @@ public class TestSnippetTag extends SnippetTester {
                         Hello, Snippet!
                         ----------------- external -----------------
                         Hello, Snippet!...more
+                        --------------------------------------------
                         
"""); @@ -2207,8 +2208,16 @@ public class TestSnippetTag extends SnippetTester { "pkg"); checkExit(Exit.ERROR); checkOutput(Output.OUT, true, - """ - A.java:4: error: contents mismatch"""); + """ + A.java:4: error: contents mismatch""", + """ + ----------------- inline ------------------- + Hello, Snippet! ...more + \s\s + ----------------- external ----------------- + Hello, Snippet! + \s\s + --------------------------------------------"""); checkOutput("pkg/A.html", true, """
invalid @snippet @@ -2219,6 +2228,7 @@ public class TestSnippetTag extends SnippetTester { ----------------- external ----------------- Hello, Snippet! + --------------------------------------------
"""); From 23a65644ae63b271ca99c55a2a60a192c4e4dfb8 Mon Sep 17 00:00:00 2001 From: Justin Lu Date: Fri, 3 Oct 2025 16:25:55 +0000 Subject: [PATCH 0054/1639] 8368981: Case Fold Locale Legacy Tags On Demand Reviewed-by: rriggs, naoto --- .../classes/sun/util/locale/LanguageTag.java | 158 ++++++++---------- .../util/Locale/CaseFoldLanguageTagTest.java | 68 ++++++-- 2 files changed, 118 insertions(+), 108 deletions(-) diff --git a/src/java.base/share/classes/sun/util/locale/LanguageTag.java b/src/java.base/share/classes/sun/util/locale/LanguageTag.java index 6036c1dd04f..0b2fee7f2cd 100644 --- a/src/java.base/share/classes/sun/util/locale/LanguageTag.java +++ b/src/java.base/share/classes/sun/util/locale/LanguageTag.java @@ -34,17 +34,21 @@ package sun.util.locale; import java.text.ParsePosition; import java.util.ArrayList; import java.util.Collections; -import java.util.HashMap; import java.util.IllformedLocaleException; import java.util.List; import java.util.Locale; -import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.StringJoiner; // List fields are unmodifiable -public record LanguageTag(String language, String script, String region, String privateuse, - List extlangs, List variants, List extensions) { +public record LanguageTag(String language, + String script, + String region, + String privateuse, + List extlangs, + List variants, + List extensions) { public static final String SEP = "-"; public static final String PRIVATEUSE = "x"; @@ -53,78 +57,6 @@ public record LanguageTag(String language, String script, String region, String private static final String EMPTY_SUBTAG = ""; private static final List EMPTY_SUBTAGS = List.of(); - // Map contains legacy language tags and its preferred mappings from - // http://www.ietf.org/rfc/rfc5646.txt - // Keys are lower-case strings. - private static final Map LEGACY; - - static { - // grandfathered = irregular ; non-redundant tags registered - // / regular ; during the RFC 3066 era - // - // irregular = "en-GB-oed" ; irregular tags do not match - // / "i-ami" ; the 'langtag' production and - // / "i-bnn" ; would not otherwise be - // / "i-default" ; considered 'well-formed' - // / "i-enochian" ; These tags are all valid, - // / "i-hak" ; but most are deprecated - // / "i-klingon" ; in favor of more modern - // / "i-lux" ; subtags or subtag - // / "i-mingo" ; combination - // / "i-navajo" - // / "i-pwn" - // / "i-tao" - // / "i-tay" - // / "i-tsu" - // / "sgn-BE-FR" - // / "sgn-BE-NL" - // / "sgn-CH-DE" - // - // regular = "art-lojban" ; these tags match the 'langtag' - // / "cel-gaulish" ; production, but their subtags - // / "no-bok" ; are not extended language - // / "no-nyn" ; or variant subtags: their meaning - // / "zh-guoyu" ; is defined by their registration - // / "zh-hakka" ; and all of these are deprecated - // / "zh-min" ; in favor of a more modern - // / "zh-min-nan" ; subtag or sequence of subtags - // / "zh-xiang" - - final String[][] entries = { - //{"tag", "preferred"}, - {"art-lojban", "jbo"}, - {"cel-gaulish", "xtg-x-cel-gaulish"}, // fallback - {"en-GB-oed", "en-GB-x-oed"}, // fallback - {"i-ami", "ami"}, - {"i-bnn", "bnn"}, - {"i-default", "en-x-i-default"}, // fallback - {"i-enochian", "und-x-i-enochian"}, // fallback - {"i-hak", "hak"}, - {"i-klingon", "tlh"}, - {"i-lux", "lb"}, - {"i-mingo", "see-x-i-mingo"}, // fallback - {"i-navajo", "nv"}, - {"i-pwn", "pwn"}, - {"i-tao", "tao"}, - {"i-tay", "tay"}, - {"i-tsu", "tsu"}, - {"no-bok", "nb"}, - {"no-nyn", "nn"}, - {"sgn-BE-FR", "sfb"}, - {"sgn-BE-NL", "vgt"}, - {"sgn-CH-DE", "sgg"}, - {"zh-guoyu", "cmn"}, - {"zh-hakka", "hak"}, - {"zh-min", "nan-x-zh-min"}, // fallback - {"zh-min-nan", "nan"}, - {"zh-xiang", "hsn"}, - }; - LEGACY = HashMap.newHashMap(entries.length); - for (String[] e : entries) { - LEGACY.put(LocaleUtils.toLowerString(e[0]), e); - } - } - /* * BNF in RFC5646 * @@ -175,14 +107,10 @@ public record LanguageTag(String language, String script, String region, String StringTokenIterator itr; var errorMsg = new StringBuilder(); - // Check if the tag is a legacy language tag - String[] gfmap = LEGACY.get(LocaleUtils.toLowerString(languageTag)); - if (gfmap != null) { - // use preferred mapping - itr = new StringTokenIterator(gfmap[1], SEP); - } else { - itr = new StringTokenIterator(languageTag, SEP); - } + // Check if the tag is a legacy tag + var pref = legacyToPreferred(LocaleUtils.toLowerString(languageTag)); + // If legacy use preferred mapping, otherwise use the tag as is + itr = new StringTokenIterator(Objects.requireNonNullElse(pref, languageTag), SEP); String language = parseLanguage(itr, pp); List extlangs; @@ -400,15 +328,24 @@ public record LanguageTag(String language, String script, String region, String public static String caseFoldTag(String tag) { parse(tag, new ParsePosition(0), false); + StringBuilder bldr = new StringBuilder(tag.length()); + String[] subtags = tag.split(SEP); // Legacy tags - String potentialLegacy = tag.toLowerCase(Locale.ROOT); - if (LEGACY.containsKey(potentialLegacy)) { - return LEGACY.get(potentialLegacy)[0]; + if (legacyToPreferred(tag.toLowerCase(Locale.ROOT)) != null) { + // Fold the legacy tag + for (int i = 0; i < subtags.length ; i++) { + // 2 ALPHA Region subtag(s) are upper, all other subtags are lower + if (i > 0 && subtags[i].length() == 2) { + bldr.append(LocaleUtils.toUpperString(subtags[i])).append(SEP); + } else { + bldr.append(LocaleUtils.toLowerString(subtags[i])).append(SEP); + } + } + bldr.setLength(bldr.length() - 1); // Remove trailing '-' + return bldr.toString(); } // Non-legacy tags - StringBuilder bldr = new StringBuilder(tag.length()); - String[] subtags = tag.split("-"); boolean privateFound = false; boolean singletonFound = false; boolean privUseVarFound = false; @@ -435,7 +372,7 @@ public record LanguageTag(String language, String script, String region, String bldr.append(subtag.toLowerCase(Locale.ROOT)); } if (i != subtags.length-1) { - bldr.append("-"); + bldr.append(SEP); } } return bldr.substring(0); @@ -567,6 +504,47 @@ public record LanguageTag(String language, String script, String region, String return new LanguageTag(language, script, region, privateuse, EMPTY_SUBTAGS, variants, extensions); } + /* + * Converts a legacy tag to its preferred mapping if it exists, otherwise null. + * The keys are mapped and stored as lower case. (Folded on demand). + * See http://www.ietf.org/rfc/rfc5646.txt Section 2.1 and 2.2.8 for the + * full syntax and case accurate legacy tags. + */ + private static String legacyToPreferred(String tag) { + if (tag.length() < 5) { + return null; + } + return switch (tag) { + case "art-lojban" -> "jbo"; + case "cel-gaulish" -> "xtg-x-cel-gaulish"; // fallback + case "en-gb-oed" -> "en-GB-x-oed"; // fallback + case "i-ami" -> "ami"; + case "i-bnn" -> "bnn"; + case "i-default" -> "en-x-i-default"; // fallback + case "i-enochian" -> "und-x-i-enochian"; // fallback + case "i-hak", + "zh-hakka" -> "hak"; + case "i-klingon" -> "tlh"; + case "i-lux" -> "lb"; + case "i-mingo" -> "see-x-i-mingo"; // fallback + case "i-navajo" -> "nv"; + case "i-pwn" -> "pwn"; + case "i-tao" -> "tao"; + case "i-tay" -> "tay"; + case "i-tsu" -> "tsu"; + case "no-bok" -> "nb"; + case "no-nyn" -> "nn"; + case "sgn-be-fr" -> "sfb"; + case "sgn-be-nl" -> "vgt"; + case "sgn-ch-de" -> "sgg"; + case "zh-guoyu" -> "cmn"; + case "zh-min" -> "nan-x-zh-min"; // fallback + case "zh-min-nan" -> "nan"; + case "zh-xiang" -> "hsn"; + default -> null; + }; + } + // // Language subtag syntax checking methods // diff --git a/test/jdk/java/util/Locale/CaseFoldLanguageTagTest.java b/test/jdk/java/util/Locale/CaseFoldLanguageTagTest.java index fdee5075229..f3babb7e4c2 100644 --- a/test/jdk/java/util/Locale/CaseFoldLanguageTagTest.java +++ b/test/jdk/java/util/Locale/CaseFoldLanguageTagTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,12 +23,11 @@ /* * @test - * @bug 8159337 + * @bug 8159337 8368981 * @summary Test Locale.caseFoldLanguageTag(String languageTag) * @run junit CaseFoldLanguageTagTest */ -import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; @@ -54,24 +53,67 @@ public class CaseFoldLanguageTagTest { @ParameterizedTest @MethodSource("wellFormedTags") - public void wellFormedTags(String tag, String foldedTag) { + void wellFormedTagsTest(String tag, String foldedTag) { assertEquals(foldedTag, Locale.caseFoldLanguageTag(tag), String.format("Folded %s", tag)); } + @ParameterizedTest + @MethodSource("legacyTags") + void legacyTagsTest(String tag) { + var lowerTag = tag.toLowerCase(Locale.ROOT); + var upperTag = tag.toUpperCase(Locale.ROOT); + assertEquals(tag, Locale.caseFoldLanguageTag(lowerTag), + String.format("Folded %s", lowerTag)); + assertEquals(tag, Locale.caseFoldLanguageTag(upperTag), + String.format("Folded %s", upperTag)); + } + @ParameterizedTest @MethodSource("illFormedTags") - public void illFormedTags(String tag) { + void illFormedTagsTest(String tag) { assertThrows(IllformedLocaleException.class, () -> Locale.caseFoldLanguageTag(tag)); } @Test - public void throwNPE() { + void throwNPETest() { assertThrows(NullPointerException.class, () -> Locale.caseFoldLanguageTag(null)); } - private static Stream wellFormedTags() { + // Well-formed legacy tags in expected case + static Stream legacyTags() { + return Stream.of( + "art-lojban", + "cel-gaulish", + "en-GB-oed", + "i-ami", + "i-bnn", + "i-default", + "i-enochian", + "i-hak", + "i-klingon", + "i-lux", + "i-mingo", + "i-navajo", + "i-pwn", + "i-tao", + "i-tay", + "i-tsu", + "no-bok", + "no-nyn", + "sgn-BE-FR", + "sgn-BE-NL", + "sgn-CH-DE", + "zh-guoyu", + "zh-hakka", + "zh-min", + "zh-min-nan", + "zh-xiang" + ); + } + + static Stream wellFormedTags() { return Stream.of( // langtag tests // language @@ -124,16 +166,6 @@ public class CaseFoldLanguageTagTest { Arguments.of("X-A-ABC", "x-a-abc"), // private w/ extended (incl. 1) Arguments.of("X-A-AB-Abcd", "x-a-ab-abcd"), // private w/ extended (incl. 1, 2, 4) - // Legacy tests - // irregular - Arguments.of("I-AMI", "i-ami"), - Arguments.of("EN-gb-OED", "en-GB-oed"), - Arguments.of("SGN-be-fr", "sgn-BE-FR"), - // regular - Arguments.of("NO-BOK", "no-bok"), - Arguments.of("CEL-GAULISH", "cel-gaulish"), - Arguments.of("ZH-MIN-NAN", "zh-min-nan"), - // Special JDK Cases (Variant and x-lvariant) Arguments.of("de-POSIX-x-URP-lvariant-Abc-Def", "de-POSIX-x-urp-lvariant-Abc-Def"), Arguments.of("JA-JPAN-JP-U-CA-JAPANESE-x-RANDOM-lvariant-JP", @@ -150,7 +182,7 @@ public class CaseFoldLanguageTagTest { ); } - private static Stream illFormedTags() { + static Stream illFormedTags() { return Stream.of( // Starts with non-language Arguments.of("xabadadoo-me"), From aee73d3568fbcb2fe7293f92154e6677c080d20c Mon Sep 17 00:00:00 2001 From: Harshitha Onkar Date: Fri, 3 Oct 2025 17:32:51 +0000 Subject: [PATCH 0055/1639] 8365424: [macos26] java/awt/Frame/DisposeTest.java fails on macOS 26 Reviewed-by: serb, azvegint --- test/jdk/java/awt/Frame/DisposeTest.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/test/jdk/java/awt/Frame/DisposeTest.java b/test/jdk/java/awt/Frame/DisposeTest.java index 08c0def638e..ea1b2428f5c 100644 --- a/test/jdk/java/awt/Frame/DisposeTest.java +++ b/test/jdk/java/awt/Frame/DisposeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,6 +44,7 @@ import java.io.IOException; public class DisposeTest { private static Frame backgroundFrame; private static Frame testedFrame; + private static final int PIXEL_OFFSET = 4; private static final Rectangle backgroundFrameBounds = new Rectangle(100, 100, 200, 200); @@ -74,8 +75,8 @@ public class DisposeTest { BufferedImage bi = robot.createScreenCapture(backgroundFrameBounds); int redPix = Color.RED.getRGB(); - for (int x = 0; x < bi.getWidth(); x++) { - for (int y = 0; y < bi.getHeight(); y++) { + for (int x = PIXEL_OFFSET; x < bi.getWidth() - PIXEL_OFFSET; x++) { + for (int y = PIXEL_OFFSET; y < bi.getHeight() - PIXEL_OFFSET; y++) { if (bi.getRGB(x, y) != redPix) { try { ImageIO.write(bi, "png", From 0935b76c6bd1fbfa0a431eedb54c51f6fe4d194e Mon Sep 17 00:00:00 2001 From: Mikael Vidstedt Date: Fri, 3 Oct 2025 17:40:37 +0000 Subject: [PATCH 0056/1639] 8369080: Use uname -m for devkit cpu detection Reviewed-by: iris, erikj --- make/devkit/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/make/devkit/Makefile b/make/devkit/Makefile index d2167bf33fa..ffa23508a13 100644 --- a/make/devkit/Makefile +++ b/make/devkit/Makefile @@ -1,5 +1,5 @@ # -# Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -58,7 +58,7 @@ COMMA := , os := $(shell uname -o) -cpu := $(shell uname -p) +cpu := $(shell uname -m) # Figure out what platform this is building on. me := $(cpu)-$(if $(findstring Linux,$(os)),linux-gnu) From 0e98ec36623d5d83172209058574a97bab1d6038 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Fri, 3 Oct 2025 17:49:59 +0000 Subject: [PATCH 0057/1639] 8367384: The ICC_Profile class may throw exceptions during serialization Reviewed-by: honkar, prr --- .../classes/java/awt/color/ICC_Profile.java | 41 +++----- .../SerializationSpecTest.java | 99 ++++++++++++++++++ .../SerializationSpecTest/empty.ser | Bin 0 -> 130 bytes .../SerializationSpecTest/invalid.ser | Bin 0 -> 141 bytes .../SerializationSpecTest/invalid_invalid.ser | Bin 0 -> 142 bytes .../SerializationSpecTest/invalid_null.ser | Bin 0 -> 142 bytes .../SerializationSpecTest/invalid_valid.ser | Bin 0 -> 7040 bytes .../invalid_wrongType.ser | Bin 0 -> 218 bytes .../SerializationSpecTest/null.ser | Bin 0 -> 131 bytes .../SerializationSpecTest/null_invalid.ser | Bin 0 -> 7030 bytes .../SerializationSpecTest/null_null.ser | Bin 0 -> 132 bytes .../SerializationSpecTest/null_valid.ser | Bin 0 -> 7030 bytes .../SerializationSpecTest/null_wrongType.ser | Bin 0 -> 208 bytes .../SerializationSpecTest/valid.ser | Bin 0 -> 140 bytes .../SerializationSpecTest/valid_invalid.ser | Bin 0 -> 141 bytes .../SerializationSpecTest/valid_null.ser | Bin 0 -> 141 bytes .../SerializationSpecTest/valid_valid.ser | Bin 0 -> 7039 bytes .../SerializationSpecTest/valid_wrongType.ser | Bin 0 -> 217 bytes .../SerializationSpecTest/wrongType.ser | Bin 0 -> 207 bytes .../wrongType_invalid.ser | Bin 0 -> 7106 bytes .../SerializationSpecTest/wrongType_null.ser | Bin 0 -> 208 bytes .../SerializationSpecTest/wrongType_valid.ser | Bin 0 -> 208 bytes .../wrongType_wrongType.ser | Bin 0 -> 217 bytes .../StandardProfilesRoundTrip.java | 73 +++++++++++++ .../ValidateICCHeaderData.java | 10 +- 25 files changed, 191 insertions(+), 32 deletions(-) create mode 100644 test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/SerializationSpecTest.java create mode 100644 test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/empty.ser create mode 100644 test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid.ser create mode 100644 test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid_invalid.ser create mode 100644 test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid_null.ser create mode 100644 test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid_valid.ser create mode 100644 test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid_wrongType.ser create mode 100644 test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null.ser create mode 100644 test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null_invalid.ser create mode 100644 test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null_null.ser create mode 100644 test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null_valid.ser create mode 100644 test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null_wrongType.ser create mode 100644 test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid.ser create mode 100644 test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid_invalid.ser create mode 100644 test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid_null.ser create mode 100644 test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid_valid.ser create mode 100644 test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid_wrongType.ser create mode 100644 test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType.ser create mode 100644 test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType_invalid.ser create mode 100644 test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType_null.ser create mode 100644 test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType_valid.ser create mode 100644 test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType_wrongType.ser create mode 100644 test/jdk/java/awt/color/ICC_Profile/Serialization/StandardProfilesRoundTrip.java diff --git a/src/java.desktop/share/classes/java/awt/color/ICC_Profile.java b/src/java.desktop/share/classes/java/awt/color/ICC_Profile.java index 8bf09195627..0c2902ba74a 100644 --- a/src/java.desktop/share/classes/java/awt/color/ICC_Profile.java +++ b/src/java.desktop/share/classes/java/awt/color/ICC_Profile.java @@ -41,6 +41,7 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.InvalidObjectException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.ObjectStreamException; @@ -1549,33 +1550,19 @@ public sealed class ICC_Profile implements Serializable private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { s.defaultReadObject(); - - String csName = (String) s.readObject(); - byte[] data = (byte[]) s.readObject(); - - int cspace = 0; // ColorSpace.CS_* constant if known - boolean isKnownPredefinedCS = false; - if (csName != null) { - isKnownPredefinedCS = true; - if (csName.equals("CS_sRGB")) { - cspace = ColorSpace.CS_sRGB; - } else if (csName.equals("CS_CIEXYZ")) { - cspace = ColorSpace.CS_CIEXYZ; - } else if (csName.equals("CS_PYCC")) { - cspace = ColorSpace.CS_PYCC; - } else if (csName.equals("CS_GRAY")) { - cspace = ColorSpace.CS_GRAY; - } else if (csName.equals("CS_LINEAR_RGB")) { - cspace = ColorSpace.CS_LINEAR_RGB; - } else { - isKnownPredefinedCS = false; - } - } - - if (isKnownPredefinedCS) { - resolvedDeserializedProfile = getInstance(cspace); - } else { - resolvedDeserializedProfile = getInstance(data); + try { + String csName = (String) s.readObject(); + byte[] data = (byte[]) s.readObject(); + resolvedDeserializedProfile = switch (csName) { + case "CS_sRGB" -> getInstance(ColorSpace.CS_sRGB); + case "CS_CIEXYZ" -> getInstance(ColorSpace.CS_CIEXYZ); + case "CS_PYCC" -> getInstance(ColorSpace.CS_PYCC); + case "CS_GRAY" -> getInstance(ColorSpace.CS_GRAY); + case "CS_LINEAR_RGB" -> getInstance(ColorSpace.CS_LINEAR_RGB); + case null, default -> getInstance(data); + }; + } catch (ClassCastException | IllegalArgumentException e) { + throw new InvalidObjectException("Invalid ICC Profile Data", e); } } diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/SerializationSpecTest.java b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/SerializationSpecTest.java new file mode 100644 index 00000000000..aa50d814264 --- /dev/null +++ b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/SerializationSpecTest.java @@ -0,0 +1,99 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.File; +import java.io.FileInputStream; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; +import java.io.OptionalDataException; + +/** + * @test + * @bug 8367384 + * @summary Verify ICC_Profile serialization per spec, all name/data cases + */ +public final class SerializationSpecTest { + + public static void main(String[] args) throws Exception { + // Serialization form for ICC_Profile includes version, profile name, + // and profile data. If the name is invalid or does not match a standard + // profile, the data is used. An exception is thrown only if both the + // name and the data are invalid, or if one of them is missing or is of + // the wrong type. + + // Naming conventions used in test file names: + // null : null reference + // valid : valid standard profile name or valid profile data (byte[]) + // invalid : unrecognized name or data with incorrect ICC header + // wrongType: incorrect type, e.g., int[] instead of String or byte[] + + // No name or data + test("empty", OptionalDataException.class); + + // Cases where only the profile name is present (no profile data) + test("null", OptionalDataException.class); + test("valid", OptionalDataException.class); + test("invalid", OptionalDataException.class); + test("wrongType", InvalidObjectException.class); + + // The test files are named as _.ser + test("null_null", InvalidObjectException.class); + test("null_valid", null); // valid data is enough if name is null + test("null_invalid", InvalidObjectException.class); + test("null_wrongType", InvalidObjectException.class); + + test("invalid_null", InvalidObjectException.class); + test("invalid_valid", null); // valid data is enough if name is invalid + test("invalid_invalid", InvalidObjectException.class); + test("invalid_wrongType", InvalidObjectException.class); + + test("wrongType_null", InvalidObjectException.class); + test("wrongType_valid", InvalidObjectException.class); + test("wrongType_invalid", InvalidObjectException.class); + test("wrongType_wrongType", InvalidObjectException.class); + + test("valid_null", null); // the valid name is enough + test("valid_valid", null); // the valid name is enough + test("valid_invalid", null); // the valid name is enough + test("valid_wrongType", InvalidObjectException.class); + } + + private static void test(String test, Class expected) { + String fileName = test + ".ser"; + File file = new File(System.getProperty("test.src", "."), fileName); + Class actual = null; + try (var fis = new FileInputStream(file); + var ois = new ObjectInputStream(fis)) + { + ois.readObject(); + } catch (Exception e) { + actual = e.getClass(); + } + if (actual != expected) { + System.err.println("Test: " + test); + System.err.println("Expected: " + expected); + System.err.println("Actual: " + actual); + throw new RuntimeException("Test failed"); + } + } +} diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/empty.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/empty.ser new file mode 100644 index 0000000000000000000000000000000000000000..3fd70024d656af1d2f6370bdc63c5c863c32c8e6 GIT binary patch literal 130 zcmZ4UmVvdnh(R_hu`E$9vAjetIX@@ANYB&RIX<8$KP@vSHOSqmj6-netmDhsm>3u; ziWsDDt34S$WyATC@12+#7(E%}Gn12{W(21eWhUliR;8x6B$gzGr4|)u=I2!uFfcGM GRsaCnJ}zni literal 0 HcmV?d00001 diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid.ser new file mode 100644 index 0000000000000000000000000000000000000000..dfe071e69dc6bfc8f50eea4dc91759c21baf0133 GIT binary patch literal 141 zcmZ4UmVvdnh(R_hu`E$9vAjetIX@@ANYB&RIX<8$KP@vSHOSqmj6-netmDhsm>3u; ziWsDDt34S$WyATC@12+#7(E%}Gn12{W(21eWhUliR;8x6B$gzGr4|)u=I2!uFfcGM RmN0NQ2gip8`TMz7008G^F=zk) literal 0 HcmV?d00001 diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid_invalid.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid_invalid.ser new file mode 100644 index 0000000000000000000000000000000000000000..60fb02f77836caff458594904ffba51da4445be9 GIT binary patch literal 142 zcmZ4UmVvdnh(R_hu`E$9vAjetIX@@ANYB&RIX<8$KP@vSHOSqmj6-netmDhsm>3u; ziWsDDt34S$WyATC@12+#7(E%}Gn12{W(21eWhUliR;8x6B$gzGr4|)u=I2!uFfcGM SmN0NQ2gip8`TMySQ~&@OMKRa_ literal 0 HcmV?d00001 diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid_null.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid_null.ser new file mode 100644 index 0000000000000000000000000000000000000000..60fb02f77836caff458594904ffba51da4445be9 GIT binary patch literal 142 zcmZ4UmVvdnh(R_hu`E$9vAjetIX@@ANYB&RIX<8$KP@vSHOSqmj6-netmDhsm>3u; ziWsDDt34S$WyATC@12+#7(E%}Gn12{W(21eWhUliR;8x6B$gzGr4|)u=I2!uFfcGM SmN0NQ2gip8`TMySQ~&@OMKRa_ literal 0 HcmV?d00001 diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid_valid.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/invalid_valid.ser new file mode 100644 index 0000000000000000000000000000000000000000..e01b5766f62f3b75de13f54d014c55168a7d2dd6 GIT binary patch literal 7040 zcmeHMXHXQ`8ok{;IS^)G$T@>V2?I#ZNpcj0VTLe-0fs1MWpM>p5D`g=AcBMiSC_bo ziYTIpf&vC~2U%3qRb0h{%A3JgwQpa&_iyX{dDB(h_w?znzVEx;x2jK_+x9y^XK;Z+ zA|sn&z{troV5TOgat%D3oTB`=sd4P&*Z?=jY@B#+)ld@#1|XLUWdD2YaA?`d8^f<0 z5de7rB{q}!&m4iVTs9+_ofpe;W@Iu#V!0XYR8DRh007DaIH$m<&;Z}HZdqIauXAjB zBlQ7;3*rfi@groX1!podB?C4BAcd335I-Xj z#0tj09`7arBw%jo|L5m_jsCYgA}fW%;x~)q^NFn34CYGX03@(dSOT8kBS^@}Ov?lS zcIIOVF26xO4in&*Z#Y?i20g2mmo{!6cN~oXl7*hmowaLjIkXf2k#sA$Z|2S?uIYeKzOsEW*$Azp5ixFW*{! zW3#djAX>$rTq^$?&|d<8l>Eu59|k~l7XV%Te{wO$0q8CPK>8swi<|u|A4)Kw0Re~t z2_OR$ff~>T`oIKO0Bc|mT!1I=1wkMjYyeD<08#)K|5FN6GTp({K01Ahq zp?HV`WkH*vT~HBJ3ROXMP&4!s)C*mJhM_U&E;IwpLw`V@U<4+?60icS2^+$6*a7x} zgW&aWJe&^a!TIn$xB{+++u$zv0(=dgfO+t9co6{z5uqU}h(1C`oDg3m0*OPo$X28f zDM#v&cBBs(LT({EK1ASwSfAH zCZpxidT1-O2RaNLkIq3Cpv%#X=uY${^aOei{SJe{&@fsU3yeD^9FvIIgxQNZjOoCf z$BbcSF^gC%RtBqwwZZyg8Q4s00k#s`hCPQJ$If9t;D|USoC(eq7lGs8cH+u$Ex3N% zIPM8<2``4%z+2&c@htpCd@;TO--o|}pTjQ^#0gpi8$u8vk+6eML1-sjB1{wB5Q#)p zq9xIv$R=(lRuE4TuMlU5A4wFFF3E`$Ny;MaBQ=rElkSqwuw}Wbcu|MycETYYKS_BZV=5AEf+m4dPDSu7+y?M%t?$PwpFZJ ztXFJGY*CylZY=IAo+7?iyhVIi{3!)X(WJOgSd@IqG0H{CEES=uQJttv>Mm*n^%8YX z0wbX%;USSIQ6%xB#HhrABt_CxGDI?0vRd-2B#(yBG-)2RWLh!p6m63BNlHP=K`K^i zk5s$VxYT=TIca<8Sm{FP4(SQ$Pcq6fE;30n`(?Ui9>}6(b!Gi!b7YUmUXpzwCn0Ao z$CN9SJ0*8d9+uaY50Kv^e@uQveo;YD!A&7ep;F6x;mvV(H6a)t7s@`8%Iin~gdN}bB6%95&bnxUGzHM=#RYDsH(Xys|OYE5gCwe7Uiwd=KS z>tJ-~I!QW*b#Cgyx@Niwy4AWj^k6-6J+|Iqy|Gp3RhFwbtLj%x>67#w^t1I_^=Axd z2Hplc4Z00p8mb#c816S5GW=>}W|VByV07P@V(e+W)40$04-;Jzrb)HQ?bYPfuB*4L z?pgiXRL?Zl^oZ#lGpd=7*>1A|voGcr=3Mi3^LYz(i)f1)iz&JU-H*PPe#H`P>1esl z@{Hw2D|4$%t5a65to5yvtXr&~uF+Z(yQX2ytc|J-!=}!LXRB-*ZF|&~XQyJvu&cLw zWUpq=vTwA1;-KS@=+Nfy($UC~>)7e|-pR^oi_>{$#M#Zc(0SB_;u7pq;pAYQg>2ttm zdacG<&f0EY;OpUg!1sZlmS4KxFa8*RKmTg~#{tFxn*)Xdsew^}ErIWX9D|C3?gwiJ zX9W+0h=xRlG>5zobq*~J<%JoBZ3(*;E*s7c?}@-hghVt(EUt4|cW~WYq*-J^C-f%WbG>Q>*IvO1v8r>58nc>T*XDr5e#MHzrFrAo(n9o`EtTNVotW9ib z?2|Z~xYD?%@iy@X;^!0W63P=^u$|ad?AM9ziM5IElYEn!l9rQ0lRHvyDbXpt9116i zGnlHFnwvV7rk7Tb#!I(KKbXG2_2M>WKpE>ZdNL*WKjx7v?X2&zX0mOwtFu4kgyfvg z70>15j%?K3xM$;&JlDMAn^2pWn+7(kY~HbXW{bm?x~1ZwE1f;ybD*nCxva44 z?ZK#n!{w&swTB3YvJUYoyeoPt)hkOXKUXDGO;kHpchtz&?5TNwn00vki2afFT7}x8 z+D}K>NAJ|R)pgZt)|Vf{9LqlTxFMur=s5j&bE9lyQR9~;P807$z=^?Ti{|DQ`Ih2V zxHYSFzAdut=8w)l_O$D_*LBc3icW%)Stp{{qf=;rl=_l)&=_73z}_jUea@JrJfl{3|6CC?W36Z-S}m(S&$TRfk3{>6p(3$p`J z1NSe6UA#T$KR9~H>(Z6Wu9q(kISiefr+9Z*cb?u&zWe%K_PwS1 z+o#dfg%89Yls}YzSpTceuN^#d-q{)FnUP02r{^qlF&*q+|JzsiJ@Vof$H7~Va{`|`R)yP8F!rW`_>*YW8zL9y;^w#w4z@p#c z!*?m~mfjbBkoj=pBmLvhr_fJNmU2F0KUaLw`O^2*>+AG#%JQ;M3kbD3u; ziWsDDt34S$WyATC@12+#7(E%}Gn12{W(21eWhUliR;8x6B$gzGr4|)u=I2!uFfcGM zmN0NQ2gip8`TMy8-604zJ0~$OUC%SGBsD#?Na)dmCEpv{Eto(?vX&+0l%@jRAb?Qk bSDKrYTGX~?sx0@E2i+hi7I;o$x>NxG?Kn+0 literal 0 HcmV?d00001 diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null.ser new file mode 100644 index 0000000000000000000000000000000000000000..1fc2022f8683b572573642900988316676339a5c GIT binary patch literal 131 zcmZ4UmVvdnh(R_hu`E$9vAjetIX@@ANYB&RIX<8$KP@vSHOSqmj6-netmDhsm>3u; ziWsDDt34S$WyATC@12+#7(E%}Gn12{W(21eWhUliR;8x6B$gzGr4|)u=I2!uFfcGM H7E}NL2_G)n literal 0 HcmV?d00001 diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null_invalid.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null_invalid.ser new file mode 100644 index 0000000000000000000000000000000000000000..b2847de4f46feabb8c141b730916d33e04d3dac5 GIT binary patch literal 7030 zcmeHMXHXQ`8ok{;IS^)G$T@>V2?L1aEP`YZg<*y;gaL*qU_usGa1{{|0Yy+j!h)+y zTqB~0A_@u^&>dtEP*!mjQBim^`l@_YulC>8`}3x&y6>rTzxuxKcHgQ#b#C*Y0G-MO z3UQ1Kh5;ip&48Jdki<1`cXSN*;U-116QX=w9Wrp@T@`)x7#M&oE|C5E*#4l>Gk5x5 zJ0JjZ2TE)v^WQoAqPT2E0y{g3<-|y11V(XF*-4zNWB>q^oX!RCMu+CNQXeolf1aQO zpO+mM+zHIYRM-fBL{1u)--dEq z^6y*{{~OR>0e}>L=hTk^Ai4{H_KV-S$Ws7x6aygrl$p-W_?8bP7|?(KM1cg50g6Bk zXajv<0xWCWr-zfD1A~F4zeQKoKYghd>3W1}8xSXaQ$I2RIL| zfa~BExC=(WW55Gb;3b#`@4*rTL0E_kQ6U*f3DSV{AQOlVt%aPSb&xL<0!2VE5C=+! za-m&N5mW+IKs8VU^b6DlU4ihjH z0%ybd@IJU4u7#W7cK8Z>3m$=a@Jo0B0SFPHAu5PILPs1CZzL3nM!3i}q!1}XYLOPC z8|g#tAv|Ob`G~@xs3>KWKFS*9h6+G2Q7NcxsJ*BP)M->Zsuy(+HG!H(Eu+b3d9)td z3hj;#M#rEt(FN!-bRD`4eGNT=obO--6$dKZ)Kxwutc_tREo5V42!%H#fxf)+KX-$%@!>aJtulcbWRK}rYYtq#t_>kRw>pcHYT

(VCi1a5JWf^Cgc$ot-9Wqa3QL?(S8)P$OkI7z>os*N0vzBAZ70R8J zdn6Cb>&pAe=g6OsACO;AP*iYLNLDzaa8+SWk)~*;7^hgOcu{dyiK?_#iLF$sbV=!j zvZS)Ta)NTXaJv4B8eJ_~tyHZ?ZC+hT-Ag@J zy-EF%23~`%5vy@nqfcW|Q%f^QbGK%P=8TrKmb+HAR+HAaHd)(NJ4L%z`@RlFhprQ^ zb5!T9F05;&8>?HXdq)q}GuLD59n~9Jg-(EjMze#_>fM&4HAkUz~ z;FY1eVW{B&!#=}hBQv7}qmxFDjVZ<+#(Bow#($aUnlMc&P42HIuXb6zeRb#RH>P@~ zQKrXCADB_iyv%l+^_YDzw=n0Lx0ugbs9Qu>R9TGCCFnl%z4RNFXiEpn?Uv^)KU$ev zrCFV|dTp(59dF%eJ+nq@P1Kr`YbI?}Z5TE+HoUdUYa`YkU(2&qv1QoS+CH;Wvt!xS z*-hK)*vHv7+rM%!a^O0&IV?I_Ic{~l?1VVEIu$w%I#ZkjoGYB4x~RIuxHP%UyPCP? zxL$TcyLq}Da2s=1aA&$VxX*i7cx?6P^(1-vc~*EnTc^8@yRO>{_VVyL=rz7xV?Aem zhd1zc_de+T#7D~~#pkyTm<>J~DmOg$HTKQ*?enAhh5I%7z4v$U-|zo8Ksz8kpeIl? zFf6bka52a!s3eFNY#6*X_*RH)2s@-R6dM{CS{J&o(Rt&cjZcbuM)`&14phndrptCG7jcVesk)|ze5w#aQg+ts$`Z=c%Xy5sat!p``exATnh zO7hf~zXCHr1 z<66^Rt65ui0&^nc#PgGZC;Lv(Pc_uZ))m!#spr)5PWztjZLnx)Xq0c<-vl?MH_bMO zHQ)W&>F3TC{g#?mT5Hi6a3=lCi(evs89nQHw&xuET+6Q-zgD$T+X~yE_ATx69kCs} z&XCTbE|0FBZtL#0-wb}MKd*AW@`B`r{TB%r^DnMk%D%L4Ir;M3m6$7&J>fl%uLfVe z-@BoA@S5kf8`oW~U+uH+yL7|m#`%7${;r$!n;o~zZ?zAY4Yb`hyWKWuKG=T8;!fvX z%e&n}Ylbck+YVp3=XCG-efRsfM%IrEjRuT97z-QYJzzbUd6@9<&7+J*OOJPqqsI%M zh&?HLD*v?hcb(r`dFH$e6HXHY&-|V}o@7qG{3G>`&r|u&$3u; ziWsDDt34S$WyATC@12+#7(E%}Gn12{W(21eWhUliR;8x6B$gzGr4|)u=I2!uFfcGM I78Fzf061YUN&o-= literal 0 HcmV?d00001 diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null_valid.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/null_valid.ser new file mode 100644 index 0000000000000000000000000000000000000000..b32c838c80ad94b311dcd5af73d74c1ad0ec9dd6 GIT binary patch literal 7030 zcmeHMXHXQ`8ok{;IS^)G2$FLU1SAX~IVZ_cRE8PC5C$BgU_=&IUxKzEQuMOnpFL`CJz=&RbduipE&_5Qr+s_uLG^jF{a-R@h}r_OEt9iUUV zKt7I<&d_IMr0O%15|X(3ZVnEceYi={?1U&k7yERacu(bEBL)T_lM7`3d+bnf>8YDT zuj~;3xdBBslljja{!v^uBY~Y2#d2h%GJ>MGDeNRpW-1Yfc!PcG8>#mgTmVl{ zg3rrN3C;v&VhU^kKq4oV%Wp#|Bs5G3I{`>Q4p0CV&=|~=WG{c`0Dc}Ih!u=~J>E?K zNWk3I`_Iq+8vSo~L{=h)#cvVE=i^vWDNH_2<>OdZB1^#Ydjzo=smXi}cI0CTF26xO z4iVtUZ#Y4KW4_^CUtM*xUv z2_~V$=A=e(IgAADujJo(`IlNEDS{UsnZ`~?)njx1&LaF=|EoHJ_42LtH&$QQ0YoeR zlS|@%1Nut;`$D02G5mpc2%8de8*gz-iD0&Vq~J z3b+n#fpPEv@W3p10T#eJuna*E79vAbNCr}b)FEBS2%9P$DlLNdFV291G)o!89k1kMZd#fFf@!N#th?%3B|-=vN462Bbau~1SgMz1V%zr!c8Jh zqCnzDi4lnfNs6SgWRPU0WR>JONgfTMY0%tg3A7^GY1#zsqm;aqom7<6KB+dTF{vf# zRnoT7QPTO+?b74YA7zweoMhr<4#;%LJd{Pr>d5-aX2>3uy(~MwN@A7eD(0&ERi{_o zmxJYWlAl+gDcCB+DU>SoDaC@m<aul@=#H*NuQp%JSzWh!Qjer(ryfl^BqT=C{BS+l}?YGRh(m-TbvhMOkA>E zF1VsyJzNjCPP)mvG2NQn7TnF;x4RE`kUac7Dm@;1>UeTJd%a*Ucdvt9Q|r~&bJllx z18+C)gWeB)G<~-C{Nju8_3^Fped1^6x6N@9ZDPw}=h+VIO7`nG*SMOvrFif7#`u+l;Dq)>Tw+9G4~N2u=L{q%BxNRz zChI2WCG)meY&o=Lf$PC-NP$u|rgW!D@PEw1Xr&p!F&j`vmlPR9b$sFFQ zvvuFrr&-QfC$dr5%y>^ixduseSDjU0oV zlAO1Dg7@_1%IEINo%zn?yOunWJZ|3PUdz2T-=n@~e?PKs?Y@eAU-DV`*9r^@$_hRe zG7GQ$VE9A%4=ekl_m32r79B0d6myCv4%i$xSt4GNRWftX>tJW8QfYqa+e4cV4V4*} z)f^@qPCLvi_bl(OP^&1e_*5BNIbLO7)m|-Ey{~%d2~7O*t8J&X7n}m8(oQ}9DdMMz(;lb$&(P1b{jC0TbqBR0zZ2@*+PTmb+r{e+ z?H=uM@9FQg?CtnP|Ch$I%4e(2NuDd}BlP9=t(?y~zjz_}!u-XUi!=S3`yX5ixpZg1 zcVOhQ$K|V6oUdFOv>QBs)#~cmA&a4&YxHYf*G;c?4x0>j+%UP(F=9H>dDHA>_bu~V zy`$?!`^Id>F5Y&$edUhZo$KT4$44guC+<#$Px9`v?moMhaPRf~^!v*Xc1@wD@*j#l zEPEvPsP0$oU)y=6ymQlz)5DMbA3vC3&b;_7<+o3>xlhPX%AP7dZF*+(?ChNL+^y#u zp3lBWez82C_q+J-)i1SP{`|`J)$l^d!t87A>yslKG5F)t<&00*PvxJrKlgs|_%gMUxUwSD0zxey)B-{+Ak+dvEg;kaLM3u; ziWsDDt34S$WyATC@12+#7(E%}Gn12{W(21eWhUliR;8x6B$gzGr4|)u=I2!uFfcGM z765G*1e=(Xn3t~SnOBmUo?0aIXu*>2jqMgpAcI)T5_3vZfi?>u)cKX>CZ!g&t(hvz RJ>@|+$YBMZ)0i$*002rXN~r(< literal 0 HcmV?d00001 diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid.ser new file mode 100644 index 0000000000000000000000000000000000000000..a6512d244cf246a938ee37fe376ee7c92bd57160 GIT binary patch literal 140 zcmZ4UmVvdnh(R_hu`E$9vAjetIX@@ANYB&RIX<8$KP@vSHOSqmj6-netmDhsm>3u; ziWsDDt34S$WyATC@12+#7(E%}Gn12{W(21eWhUliR;8x6B$gzGr4|)u=I2!uFfcGM PmN2k82ger!ZK(hNwt_Jz literal 0 HcmV?d00001 diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid_invalid.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid_invalid.ser new file mode 100644 index 0000000000000000000000000000000000000000..dbe11f2c6d651974009b5c4d96db2f45923a47dc GIT binary patch literal 141 zcmZ4UmVvdnh(R_hu`E$9vAjetIX@@ANYB&RIX<8$KP@vSHOSqmj6-netmDhsm>3u; ziWsDDt34S$WyATC@12+#7(E%}Gn12{W(21eWhUliR;8x6B$gzGr4|)u=I2!uFfcGM QmN2k82ger!Z7HY#0O%4im;e9( literal 0 HcmV?d00001 diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid_null.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid_null.ser new file mode 100644 index 0000000000000000000000000000000000000000..dbe11f2c6d651974009b5c4d96db2f45923a47dc GIT binary patch literal 141 zcmZ4UmVvdnh(R_hu`E$9vAjetIX@@ANYB&RIX<8$KP@vSHOSqmj6-netmDhsm>3u; ziWsDDt34S$WyATC@12+#7(E%}Gn12{W(21eWhUliR;8x6B$gzGr4|)u=I2!uFfcGM QmN2k82ger!Z7HY#0O%4im;e9( literal 0 HcmV?d00001 diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid_valid.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid_valid.ser new file mode 100644 index 0000000000000000000000000000000000000000..fbe90d0eb6ea8059d4cde7ff1b8e31d7531919b7 GIT binary patch literal 7039 zcmeHMXHXQ`8ok{;IS^)G$T@>V2?I#ZNpcj0VTLe-0fs1;WpM>p5D`g=AcBMiSC_bo ziUBd8pnw70K^75p6<0B#@@DW=?b}!H{o8tf-gH&>J^l5m@B41uTh*t|ZT}shGq^w@ zk&(?XVB};PFjJFLxdt9iPEmf`)Hrr>Y=E0%Hcq^+dZ-x#1CYxFvj3es99n+j=I|>= z1VA1@iOppGGe=-7m(56K=f$#|8JUcbSZ)S8m6MwW0Dv+9)+sP5gI^_!3*dE*?Qf($ zU~oY^K`lN(c1mz3GgC5PBLGr3nOr_oIV?Ov89M<;Kps#47SI^Xj5MD>*C2jEAm9qd zzh3Vq03?Xq*8k7n|H}TiHzF&A!{YafY*0sC#VlP4-G@3&^>4xnuq>?KEVh~f+b)DSQ9pc>97Or1qZ?F z;dnS5&Vvi!y>KPm0Jp>4@Ok(eJPz~V=kOu|5F$cDR1kfHjyNH{NCXmxaFH!Y5mJFP zARS0QGKAblc*qOnBMO6}qLfkkC~K5EDj3B?rK7f>_Moa!$5Gv=i>TYEY19JhE1Ha! zN9&=j&>rY8bUZo-U5KtgH=(=Gm(b(rS@b&$21CPWVJtB2m~c!YCLgm0a|qLkIfog= z%wQI=SgZ_I4{L+<#WJv&*g|X-wjFyGJBFRbe!vlNN;ngoD=q@Z!R^3R;97A5xG~%u zZV4}j*T7rheeo>(Mtljr5#Nu$iJ!$U5yS~v1RFvSA(611P)X<@Tp~;n-VljIRiY)) zpU5U|BUTbm5U&uYi62Q6k}k=K6iLb=?Iksn&XMks-jK;;O|m^Xf}Ba-OKu@wAU`61 z5TS|~hA+|-VMyyY4 zQfyJ2DsC+9E1n|0N4!;hSo|pkOVOmbP*{`#%2CP%$_y2us!^S&OzKW*BlQw>RstiT zCE+2FC{Zl&qr`~Bf+R)KR5C;|SF%R(j3keS&@^ctv}9Td?Idl2_DM=X%0VhtYPVE} z)R@$JX*p?o=~(F^=}zf!=}$7sGA=SnGW%qDWFE?*WOZfzWpiW?%U+UwAtxbcEyt8A zk~=APUmlj%l@E~5mp>|hU4BtPQNc|iO`%HRg2D?$nxeg8qGGw?fa1IoRmoO~tyHdb zR_U3tq_Tr@vT~*JMdbw*c@=k+ER}kd5tSuXE!AMv9jcwG57h{2bhS9Oa}tz6Lf2IZ|cE%=6Y{E>K4%!wHA|f3A!JB5B-WI+S1W-tL16S zk5=YZnN}yQURmo~Ct0^zKV74>CU#BZni(5a8-`824bN8DHrn=xEzeHHj$zke_t;*| zo@L);Kj)z1km%6v@Y2!9k?Yvy_}-OGKS`=p102h*d)W5LtHbF=3~FOpZFSGCt;Z(VP$cfSwpf*gZNf*u5G2WJHj zhKPnlhO~sd4|NVL3+06whHVbJ7A_mk4)2Y?MubE(MJ%p!S$AOFY@}IaVdTVmt@XL< zhd0P>NZxQJN;HZQbt)Pi9U9#l{h8s*XkaYHc*NAkEHIsz2bs@V_N;Q&e5_4uS?pY# zO;FW64(YWC|y_r$uy_es7<%}LA2p~;;oxRmIWJ`RPG#JQNN zn3|h9nx>aln8r)DNX4hnY$O*|gl`Edh z$-TZ&cjNAjb9t_L$MRA6%>2PkDx0=%n%?ZNxqb_@C1%UuR<*4KTW7bqZ9Bf5usvz} zjU7fi%67cn8M?E-K%rn;!OVAV-?bHr6mknEcUkYM`yTZ@`}>jIt9MuJ{#wK;x>{^h zTv7aa4|C7eAB=yf{9$=-+}@EA^OD1*m{LyZ#6G)y$IHaa^2%oR`|R&7S1vCqe|sS6 zz;K0WMcqNd!K{P4O7F_vD)p+;s?XI4)#EjeHJ!EcwYzKIA7ULEJ8XZrqfVi&xbD*t z_K~~wZuQ*_nhh04F-NnHK4}bT96Cln*3u-~RNVBXnbXWW9&r3(i$zOIt9)xo8{C%F zHs2oEe(Oi)AA39WJL)@Woy8}>iL4XPev1BS;-uHf!Bg~89Y1UQT-!zMD(Z&1H+C=d zB=qol!+S^jJo^Uwt^2!vG5DqVw94t4Gm>XY1_%QM1IuUg&MuxyJNM#z{P~%|sKEyp z!Y0ztkzN_@BJ=e^ybze8T-gU$5M%Re>NcT;P zo4vOzZ}pF^866n28#{m7`S#^I9(S&duN@zq2%fk*89B+j%ewpYUh=)y_p|RWJ=ivd zo+^4M_ORlS{G*0nb$;#Sne)y}J5OJK9QgRb40GoBZyCRRo-KGneo`@~G}rRfeW_61hXZun{d5h#MAlK=$e1K@oFfU0T$G~@W^ I3z51108jusz5oCK literal 0 HcmV?d00001 diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid_wrongType.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/valid_wrongType.ser new file mode 100644 index 0000000000000000000000000000000000000000..3538676276fd1b9cb42cfdd37378f05967885d59 GIT binary patch literal 217 zcmZ4UmVvdnh(R_hu`E$9vAjetIX@@ANYB&RIX<8$KP@vSHOSqmj6-netmDhsm>3u; ziWsDDt34S$WyATC@12+#7(E%}Gn12{W(21eWhUliR;8x6B$gzGr4|)u=I2!uFfcGM zmN2k82ger!Z2>w%5Nvc#VqUtQXI@EadTNo-qXkR8H?~_aflOpAOUx-v1v)_hq0X-~ ZHz~EKZOv3!?kNwtK`t!toW^vi0syHLO!oi) literal 0 HcmV?d00001 diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType.ser new file mode 100644 index 0000000000000000000000000000000000000000..3469f871ef6042f9d8d244c3ec9388cc3063423a GIT binary patch literal 207 zcmZ4UmVvdnh(R_hu`E$9vAjetIX@@ANYB&RIX<8$KP@vSHOSqmj6-netmDhsm>3u; ziWsDDt34S$WyATC@12+#7(E%}Gn12{W(21eWhUliR;8x6B$gzGr4|)u=I2!uFfcGM z0xcH=8<>-rm#*iTSCX2ZS|s#n!IJNd?G{WRb6Cp~b4pWz77HNM`IY7-r53fVnJUXY QM2_;L?iH?cY!43iv&;V3`1#}iWGb1S6H$u`Akj6^K z@7I?v0K6Lnkd(P=@!#{`BmV{wIcWlpWVtxWd>3w@0`J20OU6T(0cwmmv9(>w(S6@JYkE3+28V^qyridfILtH zsz3|q0~25YY=I+i0q(#D1b|==0b;;Pzy`@64G2LF$Oi?W7?gtTU>B$X`$0Wu0L|be zXai@#C2$qo0C&Iucm%{?47>o-;2oHQAP5VQAsVC#X+wsPIb;hlpv906v;+!+VxV{^ z2@*geC?DDcl|toE4RjD{fPR6_K$oB%s1JGojX;yoU(iPwfl06;tO*;zRxkthfCJ$O zcmH zB6UbJ(t&g%cM&l%g?vC^P&AYd$^zwr@<%O0u~Dm0>rrK>8q_gVE2;~17d3*KMtwn( z(HdxTv@@ECjz%Y;bI`@;O7s!*Y4jEJ0D27l4uiqaF~%52j6Ws@lY&``DZ}i=v|uh` z`Y@xI87vm7iZ#c&VuP_PY!5NM5L{xqoj+Z2c$P-GTDgiPL3sKk++f?$d}1a z$nWK7a+Y#TIgZ>0xmvkaxqi8q@_2bec@O!O@_F)=@~7l)%TFob6^s1gE zC=4mgP-qkzN-!mjQbsvW>7h(eu~Z|f50yhLq8_4NrjF7Onm)~o#-?qe)zhxf#uPD% z#)?eE6va}-pA~x*r-xk|N4=aj^BglTw#(RkQ|Y~p6J+N93po+-wZ zVVY{X*Yu7VY-VqkY*uS_+Z;A`Fz1=?HSb%1Uf{Gqu%K?ikOj%Y!y?sLYoeoziiEH*|xQ|_ZE^D`YznCuzlfc zJ99g(-9Eef_B8t-`_1;9_MaUb9fS_e4wH@sj`5Cr9ETW+j1Wc{hU%k`kEc(Kmn_{9eni`{hHSZ;N0Pu=z1 zIqpZ?$309vQaqYGUV2)43O!GI&U!g}t@FC*jd=Tcmw5O3P<@v9)c8E{)$>jAZS(*ceF>jJt0NrB;kHGxl;m@N@5=?H>@0)lo14KFoZ zDp=YU41$@#JA)sG7>BG5`7IO^8WLI?`Yg;QEI+I}oEE++{CN1g2+xRZ5s#LcEE6s3 zjFgXzi)@ITjq;8vj}k{)MX!s#5u+Bvi)oL=#zw{-iJe*QvwYX`u{is<;<&*T#w&7H z^sH1{$zOSHmHaB!s#Edk_^9~f@t;`1tUA_A0yAMx!Zh29y_@}lzT4exb|f6D%p+0@|Fqp4r{QT&!PTv~kE839$0D(Fhr zO3zL2%P`L<&JeG5UcGDev@lS3BooS9k=dT5DETqp6q$&A5RGIn&aTaVpA(sLDwmQg z$i2D7Y|WN6<9WV$hu5Okve$Oz>*g2akF4`pcW^zlK4E?52K^018^$*JZ9G;$C`c{1 zRcKvUUifxX)TWLi&7zG(qd)ll&{!;2EG!<{?6P_PkEkDcKlW}}xTSi_ml96N^-}B7 z%F<6|?6T`W+5A-X)7PzuTYI-TY}>aTvt6)#aEIHDW95|cyz~ zfOp{jLBE5obw+iShcJh-4?U}otnWU|INWeV?MUg7&qoDE#mB;qbu~CPG#uABzO4~% z6g5sZ#Wmge+56}AW{c*7E%cVs6X1mC#PeU`e;GU(c(U^p<5csnhQIDPO*>uE3bn3j zoo-8R6Sv2-_niqi)7jzDar!sQ-;SQuJzIND>D;#Sg!4t`zh20@Fmo~E;?$+2OQW5u zIv-t*zI?AMw5#_@;FW7veXm~b_UOKF&Gp*Z9_OAj*BRH_ZaCa%y=i~*^ey{ar+XcG zTW>qwZolJnr=xFC-}!#G{!4eg?_Ryfymw<@=|JD$vcda9aYN$!ocj|G_zzw`%zilc zXyY(?xa6_I?F)c*BJ4 z#Mw#T$ve-NKOcLM@nUYO_)p58dtREn{PmUltDDo&(_^oNufP6P_D1#1(YJPQJ7+>> zp1ezYH#b}IUiJO44~!4pAEQ2w&*gl=eyaLx`nlsv;FsaAXd;ys+AoB%ezJSaZkof{KU*P}P7nnc0k*EPgst67Z0T8hkfF-v8sICFP LC{c305SRNe4T)CE literal 0 HcmV?d00001 diff --git a/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType_null.ser b/test/jdk/java/awt/color/ICC_Profile/Serialization/SerializationSpecTest/wrongType_null.ser new file mode 100644 index 0000000000000000000000000000000000000000..2c1536cc09423dfa9117647e3d5206ba5763c15b GIT binary patch literal 208 zcmZ4UmVvdnh(R_hu`E$9vAjetIX@@ANYB&RIX<8$KP@vSHOSqmj6-netmDhsm>3u; ziWsDDt34S$WyATC@12+#7(E%}Gn12{W(21eWhUliR;8x6B$gzGr4|)u=I2!uFfcGM z0xcH=8<>-rm#*iTSCX2ZS|s#n!IJNd?G{WRb6Cp~b4pWz77HNM`IY7-r53fVnJUXY R3u; ziWsDDt34S$WyATC@12+#7(E%}Gn12{W(21eWhUliR;8x6B$gzGr4|)u=I2!uFfcGM z0xcH=8<>-rm#*iTSCX2ZS|s#n!IJNd?G{WRb6Cp~b4pWz77HNM`IY7-r53fVnJUXY R3u; ziWsDDt34S$WyATC@12+#7(E%}Gn12{W(21eWhUliR;8x6B$gzGr4|)u=I2!uFfcGM z0xcH=8<>-rm#*iTSCX2ZS|s#n!IJNd?G{WRb6Cp~b4pWz77HNM`IY7-r53fVnJUXY X Date: Fri, 3 Oct 2025 18:45:34 +0000 Subject: [PATCH 0058/1639] 8356202: Cleanup Source code in String Implementation Classes Reviewed-by: jpai, rgiulietti, liach --- .../share/classes/java/lang/StringLatin1.java | 124 +++++--------- .../share/classes/java/lang/StringUTF16.java | 161 +++++++++--------- 2 files changed, 127 insertions(+), 158 deletions(-) diff --git a/src/java.base/share/classes/java/lang/StringLatin1.java b/src/java.base/share/classes/java/lang/StringLatin1.java index da3acbe5f0a..61c62d049bc 100644 --- a/src/java.base/share/classes/java/lang/StringLatin1.java +++ b/src/java.base/share/classes/java/lang/StringLatin1.java @@ -41,61 +41,49 @@ import static java.lang.String.checkIndex; import static java.lang.String.checkOffset; final class StringLatin1 { - public static char charAt(byte[] value, int index) { + static char charAt(byte[] value, int index) { checkIndex(index, value.length); return (char)(value[index] & 0xff); } - public static boolean canEncode(char cp) { + static boolean canEncode(char cp) { return cp <= 0xff; } - public static boolean canEncode(int cp) { + static boolean canEncode(int cp) { return cp >=0 && cp <= 0xff; } - public static byte coderFromChar(char cp) { + static byte coderFromChar(char cp) { return (byte)((0xff - cp) >>> (Integer.SIZE - 1)); } - public static int length(byte[] value) { + static int length(byte[] value) { return value.length; } - public static int codePointAt(byte[] value, int index, int end) { - return value[index] & 0xff; - } - - public static int codePointBefore(byte[] value, int index) { - return value[index - 1] & 0xff; - } - - public static int codePointCount(byte[] value, int beginIndex, int endIndex) { - return endIndex - beginIndex; - } - - public static char[] toChars(byte[] value) { + static char[] toChars(byte[] value) { char[] dst = new char[value.length]; inflate(value, 0, dst, 0, value.length); return dst; } - public static byte[] inflate(byte[] value, int off, int len) { + static byte[] inflate(byte[] value, int off, int len) { byte[] ret = StringUTF16.newBytesFor(len); inflate(value, off, ret, 0, len); return ret; } - public static void getChars(byte[] value, int srcBegin, int srcEnd, char[] dst, int dstBegin) { + static void getChars(byte[] value, int srcBegin, int srcEnd, char[] dst, int dstBegin) { inflate(value, srcBegin, dst, dstBegin, srcEnd - srcBegin); } - public static void getBytes(byte[] value, int srcBegin, int srcEnd, byte[] dst, int dstBegin) { + static void getBytes(byte[] value, int srcBegin, int srcEnd, byte[] dst, int dstBegin) { System.arraycopy(value, srcBegin, dst, dstBegin, srcEnd - srcBegin); } @IntrinsicCandidate - public static boolean equals(byte[] value, byte[] other) { + static boolean equals(byte[] value, byte[] other) { if (value.length == other.length) { for (int i = 0; i < value.length; i++) { if (value[i] != other[i]) { @@ -108,20 +96,20 @@ final class StringLatin1 { } @IntrinsicCandidate - public static int compareTo(byte[] value, byte[] other) { + static int compareTo(byte[] value, byte[] other) { int len1 = value.length; int len2 = other.length; return compareTo(value, other, len1, len2); } - public static int compareTo(byte[] value, byte[] other, int len1, int len2) { + static int compareTo(byte[] value, byte[] other, int len1, int len2) { int lim = Math.min(len1, len2); int k = ArraysSupport.mismatch(value, other, lim); return (k < 0) ? len1 - len2 : getChar(value, k) - getChar(other, k); } @IntrinsicCandidate - public static int compareToUTF16(byte[] value, byte[] other) { + static int compareToUTF16(byte[] value, byte[] other) { int len1 = length(value); int len2 = StringUTF16.length(other); return compareToUTF16Values(value, other, len1, len2); @@ -130,7 +118,7 @@ final class StringLatin1 { /* * Checks the boundary and then compares the byte arrays. */ - public static int compareToUTF16(byte[] value, byte[] other, int len1, int len2) { + static int compareToUTF16(byte[] value, byte[] other, int len1, int len2) { checkOffset(len1, length(value)); checkOffset(len2, StringUTF16.length(other)); @@ -149,7 +137,7 @@ final class StringLatin1 { return len1 - len2; } - public static int compareToCI(byte[] value, byte[] other) { + static int compareToCI(byte[] value, byte[] other) { int len1 = value.length; int len2 = other.length; int lim = Math.min(len1, len2); @@ -169,7 +157,7 @@ final class StringLatin1 { return len1 - len2; } - public static int compareToCI_UTF16(byte[] value, byte[] other) { + static int compareToCI_UTF16(byte[] value, byte[] other) { int len1 = length(value); int len2 = StringUTF16.length(other); int lim = Math.min(len1, len2); @@ -191,12 +179,12 @@ final class StringLatin1 { return len1 - len2; } - public static int hashCode(byte[] value) { + static int hashCode(byte[] value) { return ArraysSupport.hashCodeOfUnsigned(value, 0, value.length, 0); } // Caller must ensure that from- and toIndex are within bounds - public static int indexOf(byte[] value, int ch, int fromIndex, int toIndex) { + static int indexOf(byte[] value, int ch, int fromIndex, int toIndex) { if (!canEncode(ch)) { return -1; } @@ -215,7 +203,7 @@ final class StringLatin1 { } @IntrinsicCandidate - public static int indexOf(byte[] value, byte[] str) { + static int indexOf(byte[] value, byte[] str) { if (str.length == 0) { return 0; } @@ -226,7 +214,7 @@ final class StringLatin1 { } @IntrinsicCandidate - public static int indexOf(byte[] value, int valueCount, byte[] str, int strCount, int fromIndex) { + static int indexOf(byte[] value, int valueCount, byte[] str, int strCount, int fromIndex) { byte first = str[0]; int max = (valueCount - strCount); for (int i = fromIndex; i <= max; i++) { @@ -248,8 +236,8 @@ final class StringLatin1 { return -1; } - public static int lastIndexOf(byte[] src, int srcCount, - byte[] tgt, int tgtCount, int fromIndex) { + static int lastIndexOf(byte[] src, int srcCount, + byte[] tgt, int tgtCount, int fromIndex) { int min = tgtCount - 1; int i = min + fromIndex; int strLastIndex = tgtCount - 1; @@ -276,7 +264,7 @@ final class StringLatin1 { } } - public static int lastIndexOf(final byte[] value, int ch, int fromIndex) { + static int lastIndexOf(final byte[] value, int ch, int fromIndex) { if (!canEncode(ch)) { return -1; } @@ -289,7 +277,7 @@ final class StringLatin1 { return -1; } - public static String replace(byte[] value, char oldChar, char newChar) { + static String replace(byte[] value, char oldChar, char newChar) { if (canEncode(oldChar)) { int len = value.length; int i = -1; @@ -326,8 +314,8 @@ final class StringLatin1 { return null; // for string to return this; } - public static String replace(byte[] value, int valLen, byte[] targ, - int targLen, byte[] repl, int replLen) + static String replace(byte[] value, int valLen, byte[] targ, + int targLen, byte[] repl, int replLen) { assert targLen > 0; int i, j, p = 0; @@ -377,8 +365,8 @@ final class StringLatin1 { } // case insensitive - public static boolean regionMatchesCI(byte[] value, int toffset, - byte[] other, int ooffset, int len) { + static boolean regionMatchesCI(byte[] value, int toffset, + byte[] other, int ooffset, int len) { int last = toffset + len; while (toffset < last) { byte b1 = value[toffset++]; @@ -391,8 +379,8 @@ final class StringLatin1 { return true; } - public static boolean regionMatchesCI_UTF16(byte[] value, int toffset, - byte[] other, int ooffset, int len) { + static boolean regionMatchesCI_UTF16(byte[] value, int toffset, + byte[] other, int ooffset, int len) { int last = toffset + len; while (toffset < last) { char c1 = (char)(value[toffset++] & 0xff); @@ -413,7 +401,7 @@ final class StringLatin1 { return true; } - public static String toLowerCase(String str, byte[] value, Locale locale) { + static String toLowerCase(String str, byte[] value, Locale locale) { if (locale == null) { throw new NullPointerException(); } @@ -480,7 +468,7 @@ final class StringLatin1 { return StringUTF16.newString(result, 0, resultOffset); } - public static String toUpperCase(String str, byte[] value, Locale locale) { + static String toUpperCase(String str, byte[] value, Locale locale) { if (locale == null) { throw new NullPointerException(); } @@ -560,7 +548,7 @@ final class StringLatin1 { return StringUTF16.newString(result, 0, resultOffset); } - public static String trim(byte[] value) { + static String trim(byte[] value) { int len = value.length; int st = 0; while ((st < len) && ((value[st] & 0xff) <= ' ')) { @@ -573,7 +561,7 @@ final class StringLatin1 { newString(value, st, len - st) : null; } - public static int indexOfNonWhitespace(byte[] value) { + static int indexOfNonWhitespace(byte[] value) { int length = value.length; int left = 0; while (left < length) { @@ -586,9 +574,8 @@ final class StringLatin1 { return left; } - public static int lastIndexOfNonWhitespace(byte[] value) { - int length = value.length; - int right = length; + static int lastIndexOfNonWhitespace(byte[] value) { + int right = value.length; while (0 < right) { char ch = getChar(value, right - 1); if (ch != ' ' && ch != '\t' && !CharacterDataLatin1.instance.isWhitespace(ch)) { @@ -599,7 +586,7 @@ final class StringLatin1 { return right; } - public static String strip(byte[] value) { + static String strip(byte[] value) { int left = indexOfNonWhitespace(value); if (left == value.length) { return ""; @@ -609,12 +596,12 @@ final class StringLatin1 { return ifChanged ? newString(value, left, right - left) : null; } - public static String stripLeading(byte[] value) { + static String stripLeading(byte[] value) { int left = indexOfNonWhitespace(value); return (left != 0) ? newString(value, left, value.length - left) : null; } - public static String stripTrailing(byte[] value) { + static String stripTrailing(byte[] value) { int right = lastIndexOfNonWhitespace(value); return (right != value.length) ? newString(value, 0, right) : null; } @@ -713,14 +700,14 @@ final class StringLatin1 { return StreamSupport.stream(LinesSpliterator.spliterator(value), false); } - public static void putCharsAt(byte[] value, int i, char c1, char c2, char c3, char c4) { + static void putCharsAt(byte[] value, int i, char c1, char c2, char c3, char c4) { value[i] = (byte)c1; value[i + 1] = (byte)c2; value[i + 2] = (byte)c3; value[i + 3] = (byte)c4; } - public static void putCharsAt(byte[] value, int i, char c1, char c2, char c3, char c4, char c5) { + static void putCharsAt(byte[] value, int i, char c1, char c2, char c3, char c4, char c5) { value[i] = (byte)c1; value[i + 1] = (byte)c2; value[i + 2] = (byte)c3; @@ -728,32 +715,15 @@ final class StringLatin1 { value[i + 4] = (byte)c5; } - public static void putChar(byte[] val, int index, int c) { - //assert (canEncode(c)); - val[index] = (byte)(c); - } - - public static char getChar(byte[] val, int index) { + static char getChar(byte[] val, int index) { return (char)(val[index] & 0xff); } - public static byte[] toBytes(int[] val, int off, int len) { - byte[] ret = new byte[len]; - for (int i = 0; i < len; i++) { - int cp = val[off++]; - if (!canEncode(cp)) { - return null; - } - ret[i] = (byte)cp; - } - return ret; - } - - public static byte[] toBytes(char c) { + static byte[] toBytes(char c) { return new byte[] { (byte)c }; } - public static String newString(byte[] val, int index, int len) { + static String newString(byte[] val, int index, int len) { if (len == 0) { return ""; } @@ -763,7 +733,7 @@ final class StringLatin1 { // inflatedCopy byte[] -> char[] @IntrinsicCandidate - public static void inflate(byte[] src, int srcOff, char[] dst, int dstOff, int len) { + static void inflate(byte[] src, int srcOff, char[] dst, int dstOff, int len) { for (int i = 0; i < len; i++) { dst[dstOff++] = (char)(src[srcOff++] & 0xff); } @@ -771,7 +741,7 @@ final class StringLatin1 { // inflatedCopy byte[] -> byte[] @IntrinsicCandidate - public static void inflate(byte[] src, int srcOff, byte[] dst, int dstOff, int len) { + static void inflate(byte[] src, int srcOff, byte[] dst, int dstOff, int len) { StringUTF16.inflate(src, srcOff, dst, dstOff, len); } @@ -824,7 +794,7 @@ final class StringLatin1 { } @Override - public long estimateSize() { return (long)(fence - index); } + public long estimateSize() { return fence - index; } @Override public int characteristics() { diff --git a/src/java.base/share/classes/java/lang/StringUTF16.java b/src/java.base/share/classes/java/lang/StringUTF16.java index 08b4072fc35..4e31c9728e9 100644 --- a/src/java.base/share/classes/java/lang/StringUTF16.java +++ b/src/java.base/share/classes/java/lang/StringUTF16.java @@ -54,13 +54,13 @@ final class StringUTF16 { // Return a new byte array for a UTF16-coded string for len chars // Throw an exception if out of range - public static byte[] newBytesFor(int len) { + static byte[] newBytesFor(int len) { return new byte[newBytesLength(len)]; } // Check the size of a UTF16-coded string // Throw an exception if out of range - public static int newBytesLength(int len) { + static int newBytesLength(int len) { if (len < 0) { throw new NegativeArraySizeException(); } @@ -89,7 +89,7 @@ final class StringUTF16 { ((val[index] & 0xff) << LO_BYTE_SHIFT)); } - public static int length(byte[] value) { + static int length(byte[] value) { return value.length >> 1; } @@ -111,7 +111,7 @@ final class StringUTF16 { return c1; } - public static int codePointAt(byte[] value, int index, int end) { + static int codePointAt(byte[] value, int index, int end) { return codePointAt(value, index, end, false /* unchecked */); } @@ -134,7 +134,7 @@ final class StringUTF16 { return c2; } - public static int codePointBefore(byte[] value, int index) { + static int codePointBefore(byte[] value, int index) { return codePointBefore(value, index, false /* unchecked */); } @@ -155,11 +155,11 @@ final class StringUTF16 { return count; } - public static int codePointCount(byte[] value, int beginIndex, int endIndex) { + static int codePointCount(byte[] value, int beginIndex, int endIndex) { return codePointCount(value, beginIndex, endIndex, false /* unchecked */); } - public static char[] toChars(byte[] value) { + static char[] toChars(byte[] value) { char[] dst = new char[value.length >> 1]; getChars(value, 0, dst.length, dst, 0); return dst; @@ -173,7 +173,7 @@ final class StringUTF16 { * @param len a length */ @IntrinsicCandidate - public static byte[] toBytes(char[] value, int off, int len) { + static byte[] toBytes(char[] value, int off, int len) { byte[] val = newBytesFor(len); for (int i = 0; i < len; i++) { putChar(val, i, value[off]); @@ -218,7 +218,7 @@ final class StringUTF16 { * @param count count of chars to be compressed, {@code count} > 0 */ @ForceInline - public static byte[] compress(final char[] val, final int off, final int count) { + static byte[] compress(final char[] val, final int off, final int count) { byte[] latin1 = new byte[count]; int ndx = compress(val, off, latin1, 0, count); if (ndx != count) { @@ -245,7 +245,7 @@ final class StringUTF16 { * @param off starting offset * @param count count of chars to be compressed, {@code count} > 0 */ - public static byte[] compress(final byte[] val, final int off, final int count) { + static byte[] compress(final byte[] val, final int off, final int count) { byte[] latin1 = new byte[count]; int ndx = compress(val, off, latin1, 0, count); if (ndx != count) {// Switch to UTF16 @@ -279,7 +279,7 @@ final class StringUTF16 { * @param off starting offset * @param count length of code points to be compressed, length > 0 */ - public static byte[] compress(final int[] val, int off, final int count) { + static byte[] compress(final int[] val, int off, final int count) { // Optimistically copy all latin1 code points to the destination byte[] latin1 = new byte[count]; final int end = off + count; @@ -389,7 +389,7 @@ final class StringUTF16 { // compressedCopy char[] -> byte[] @IntrinsicCandidate - public static int compress(char[] src, int srcOff, byte[] dst, int dstOff, int len) { + static int compress(char[] src, int srcOff, byte[] dst, int dstOff, int len) { for (int i = 0; i < len; i++) { char c = src[srcOff]; if (c > 0xff) { @@ -404,7 +404,7 @@ final class StringUTF16 { // compressedCopy byte[] -> byte[] @IntrinsicCandidate - public static int compress(byte[] src, int srcOff, byte[] dst, int dstOff, int len) { + static int compress(byte[] src, int srcOff, byte[] dst, int dstOff, int len) { // We need a range check here because 'getChar' has no checks checkBoundsOffCount(srcOff, len, src); for (int i = 0; i < len; i++) { @@ -420,7 +420,7 @@ final class StringUTF16 { } // Create the UTF16 buffer for !COMPACT_STRINGS - public static byte[] toBytes(int[] val, int index, int len) { + static byte[] toBytes(int[] val, int index, int len) { final int end = index + len; int n = computeCodePointSize(val, index, end); @@ -428,7 +428,7 @@ final class StringUTF16 { return extractCodepoints(val, index, end, buf, 0); } - public static byte[] toBytes(char c) { + static byte[] toBytes(char c) { byte[] result = new byte[2]; putChar(result, 0, c); return result; @@ -442,7 +442,7 @@ final class StringUTF16 { } @IntrinsicCandidate - public static void getChars(byte[] value, int srcBegin, int srcEnd, char[] dst, int dstBegin) { + static void getChars(byte[] value, int srcBegin, int srcEnd, char[] dst, int dstBegin) { // We need a range check here because 'getChar' has no checks if (srcBegin < srcEnd) { checkBoundsOffCount(srcBegin, srcEnd - srcBegin, value); @@ -453,7 +453,7 @@ final class StringUTF16 { } /* @see java.lang.String.getBytes(int, int, byte[], int) */ - public static void getBytes(byte[] value, int srcBegin, int srcEnd, byte[] dst, int dstBegin) { + static void getBytes(byte[] value, int srcBegin, int srcEnd, byte[] dst, int dstBegin) { srcBegin <<= 1; srcEnd <<= 1; for (int i = srcBegin + (1 >> LO_BYTE_SHIFT); i < srcEnd; i += 2) { @@ -462,7 +462,7 @@ final class StringUTF16 { } @IntrinsicCandidate - public static int compareTo(byte[] value, byte[] other) { + static int compareTo(byte[] value, byte[] other) { int len1 = length(value); int len2 = length(other); return compareValues(value, other, len1, len2); @@ -471,7 +471,7 @@ final class StringUTF16 { /* * Checks the boundary and then compares the byte arrays. */ - public static int compareTo(byte[] value, byte[] other, int len1, int len2) { + static int compareTo(byte[] value, byte[] other, int len1, int len2) { checkOffset(len1, value); checkOffset(len2, other); @@ -491,15 +491,15 @@ final class StringUTF16 { } @IntrinsicCandidate - public static int compareToLatin1(byte[] value, byte[] other) { + static int compareToLatin1(byte[] value, byte[] other) { return -StringLatin1.compareToUTF16(other, value); } - public static int compareToLatin1(byte[] value, byte[] other, int len1, int len2) { + static int compareToLatin1(byte[] value, byte[] other, int len1, int len2) { return -StringLatin1.compareToUTF16(other, value, len2, len1); } - public static int compareToCI(byte[] value, byte[] other) { + static int compareToCI(byte[] value, byte[] other) { return compareToCIImpl(value, 0, length(value), other, 0, length(other)); } @@ -512,8 +512,8 @@ final class StringUTF16 { assert olast <= length(other); for (int k1 = toffset, k2 = ooffset; k1 < tlast && k2 < olast; k1++, k2++) { - int cp1 = (int)getChar(value, k1); - int cp2 = (int)getChar(other, k2); + int cp1 = getChar(value, k1); + int cp2 = getChar(other, k2); if (cp1 == cp2 || compareCodePointCI(cp1, cp2) == 0) { continue; @@ -588,16 +588,16 @@ final class StringUTF16 { return cp; } - public static int compareToCI_Latin1(byte[] value, byte[] other) { + static int compareToCI_Latin1(byte[] value, byte[] other) { return -StringLatin1.compareToCI_UTF16(other, value); } - public static int hashCode(byte[] value) { + static int hashCode(byte[] value) { return ArraysSupport.hashCodeOfUTF16(value, 0, value.length >> 1, 0); } // Caller must ensure that from- and toIndex are within bounds - public static int indexOf(byte[] value, int ch, int fromIndex, int toIndex) { + static int indexOf(byte[] value, int ch, int fromIndex, int toIndex) { if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) { // handle most cases here (ch is a BMP code point or a // negative value (invalid code point)) @@ -608,7 +608,7 @@ final class StringUTF16 { } @IntrinsicCandidate - public static int indexOf(byte[] value, byte[] str) { + static int indexOf(byte[] value, byte[] str) { if (str.length == 0) { return 0; } @@ -619,7 +619,7 @@ final class StringUTF16 { } @IntrinsicCandidate - public static int indexOf(byte[] value, int valueCount, byte[] str, int strCount, int fromIndex) { + static int indexOf(byte[] value, int valueCount, byte[] str, int strCount, int fromIndex) { checkBoundsBeginEnd(fromIndex, valueCount, value); checkBoundsBeginEnd(0, strCount, str); return indexOfUnsafe(value, valueCount, str, strCount, fromIndex); @@ -657,7 +657,7 @@ final class StringUTF16 { * Handles indexOf Latin1 substring in UTF16 string. */ @IntrinsicCandidate - public static int indexOfLatin1(byte[] value, byte[] str) { + static int indexOfLatin1(byte[] value, byte[] str) { if (str.length == 0) { return 0; } @@ -668,13 +668,13 @@ final class StringUTF16 { } @IntrinsicCandidate - public static int indexOfLatin1(byte[] src, int srcCount, byte[] tgt, int tgtCount, int fromIndex) { + static int indexOfLatin1(byte[] src, int srcCount, byte[] tgt, int tgtCount, int fromIndex) { checkBoundsBeginEnd(fromIndex, srcCount, src); String.checkBoundsBeginEnd(0, tgtCount, tgt.length); return indexOfLatin1Unsafe(src, srcCount, tgt, tgtCount, fromIndex); } - public static int indexOfLatin1Unsafe(byte[] src, int srcCount, byte[] tgt, int tgtCount, int fromIndex) { + static int indexOfLatin1Unsafe(byte[] src, int srcCount, byte[] tgt, int tgtCount, int fromIndex) { assert fromIndex >= 0; assert tgtCount > 0; assert tgtCount <= tgt.length; @@ -730,8 +730,8 @@ final class StringUTF16 { } // srcCoder == UTF16 && tgtCoder == UTF16 - public static int lastIndexOf(byte[] src, int srcCount, - byte[] tgt, int tgtCount, int fromIndex) { + static int lastIndexOf(byte[] src, int srcCount, + byte[] tgt, int tgtCount, int fromIndex) { assert fromIndex >= 0; assert tgtCount > 0; assert tgtCount <= length(tgt); @@ -765,7 +765,7 @@ final class StringUTF16 { } } - public static int lastIndexOf(byte[] value, int ch, int fromIndex) { + static int lastIndexOf(byte[] value, int ch, int fromIndex) { if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) { // handle most cases here (ch is a BMP code point or a // negative value (invalid code point)) @@ -798,7 +798,7 @@ final class StringUTF16 { return -1; } - public static String replace(byte[] value, char oldChar, char newChar) { + static String replace(byte[] value, char oldChar, char newChar) { int len = value.length >> 1; int i = -1; while (++i < len) { @@ -829,9 +829,9 @@ final class StringUTF16 { return null; } - public static String replace(byte[] value, int valLen, boolean valLat1, - byte[] targ, int targLen, boolean targLat1, - byte[] repl, int replLen, boolean replLat1) + static String replace(byte[] value, int valLen, boolean valLat1, + byte[] targ, int targLen, boolean targLat1, + byte[] repl, int replLen, boolean replLat1) { assert targLen > 0; assert !valLat1 || !targLat1 || !replLat1; @@ -944,18 +944,18 @@ final class StringUTF16 { return new String(result, UTF16); } - public static boolean regionMatchesCI(byte[] value, int toffset, - byte[] other, int ooffset, int len) { + static boolean regionMatchesCI(byte[] value, int toffset, + byte[] other, int ooffset, int len) { return compareToCIImpl(value, toffset, len, other, ooffset, len) == 0; } - public static boolean regionMatchesCI_Latin1(byte[] value, int toffset, - byte[] other, int ooffset, - int len) { + static boolean regionMatchesCI_Latin1(byte[] value, int toffset, + byte[] other, int ooffset, + int len) { return StringLatin1.regionMatchesCI_UTF16(other, ooffset, value, toffset, len); } - public static String toLowerCase(String str, byte[] value, Locale locale) { + static String toLowerCase(String str, byte[] value, Locale locale) { if (locale == null) { throw new NullPointerException(); } @@ -965,7 +965,7 @@ final class StringUTF16 { // Now check if there are any characters that need to be changed, or are surrogate for (first = 0 ; first < len; first++) { - int cp = (int)getChar(value, first); + int cp = getChar(value, first); if (Character.isSurrogate((char)cp)) { hasSurr = true; break; @@ -988,7 +988,7 @@ final class StringUTF16 { } int bits = 0; for (int i = first; i < len; i++) { - int cp = (int)getChar(value, i); + int cp = getChar(value, i); if (cp == '\u03A3' || // GREEK CAPITAL LETTER SIGMA Character.isSurrogate((char)cp)) { return toLowerCaseEx(str, value, result, i, locale, false); @@ -1003,7 +1003,7 @@ final class StringUTF16 { bits |= cp; putChar(result, i, cp); } - if (bits < 0 || bits > 0xff) { + if (bits > 0xff) { return new String(result, UTF16); } else { return newString(result, 0, len); @@ -1059,7 +1059,7 @@ final class StringUTF16 { return newString(result, 0, resultOffset); } - public static String toUpperCase(String str, byte[] value, Locale locale) { + static String toUpperCase(String str, byte[] value, Locale locale) { if (locale == null) { throw new NullPointerException(); } @@ -1069,7 +1069,7 @@ final class StringUTF16 { // Now check if there are any characters that need to be changed, or are surrogate for (first = 0 ; first < len; first++) { - int cp = (int)getChar(value, first); + int cp = getChar(value, first); if (Character.isSurrogate((char)cp)) { hasSurr = true; break; @@ -1093,7 +1093,7 @@ final class StringUTF16 { } int bits = 0; for (int i = first; i < len; i++) { - int cp = (int)getChar(value, i); + int cp = getChar(value, i); if (Character.isSurrogate((char)cp)) { return toUpperCaseEx(str, value, result, i, locale, false); } @@ -1104,7 +1104,7 @@ final class StringUTF16 { bits |= cp; putChar(result, i, cp); } - if (bits < 0 || bits > 0xff) { + if (bits > 0xff) { return new String(result, UTF16); } else { return newString(result, 0, len); @@ -1164,7 +1164,7 @@ final class StringUTF16 { return newString(result, 0, resultOffset); } - public static String trim(byte[] value) { + static String trim(byte[] value) { int length = value.length >> 1; int len = length; int st = 0; @@ -1179,7 +1179,7 @@ final class StringUTF16 { null; } - public static int indexOfNonWhitespace(byte[] value) { + static int indexOfNonWhitespace(byte[] value) { int length = value.length >> 1; int left = 0; while (left < length) { @@ -1192,9 +1192,8 @@ final class StringUTF16 { return left; } - public static int lastIndexOfNonWhitespace(byte[] value) { - int length = value.length >>> 1; - int right = length; + static int lastIndexOfNonWhitespace(byte[] value) { + int right = value.length >>> 1; while (0 < right) { int codepoint = codePointBefore(value, right); if (codepoint != ' ' && codepoint != '\t' && !Character.isWhitespace(codepoint)) { @@ -1205,7 +1204,7 @@ final class StringUTF16 { return right; } - public static String strip(byte[] value) { + static String strip(byte[] value) { int length = value.length >>> 1; int left = indexOfNonWhitespace(value); if (left == length) { @@ -1216,13 +1215,13 @@ final class StringUTF16 { return ifChanged ? newString(value, left, right - left) : null; } - public static String stripLeading(byte[] value) { + static String stripLeading(byte[] value) { int length = value.length >>> 1; int left = indexOfNonWhitespace(value); return (left != 0) ? newString(value, left, length - left) : null; } - public static String stripTrailing(byte[] value) { + static String stripTrailing(byte[] value) { int length = value.length >>> 1; int right = lastIndexOfNonWhitespace(value); return (right != length) ? newString(value, 0, right) : null; @@ -1322,7 +1321,7 @@ final class StringUTF16 { return StreamSupport.stream(LinesSpliterator.spliterator(value), false); } - public static String newString(byte[] val, int index, int len) { + static String newString(byte[] val, int index, int len) { if (len == 0) { return ""; } @@ -1388,7 +1387,7 @@ final class StringUTF16 { } @Override - public long estimateSize() { return (long)(fence - index); } + public long estimateSize() { return fence - index; } @Override public int characteristics() { @@ -1473,7 +1472,7 @@ final class StringUTF16 { } @Override - public long estimateSize() { return (long)(fence - index); } + public long estimateSize() { return fence - index; } @Override public int characteristics() { @@ -1483,12 +1482,12 @@ final class StringUTF16 { //////////////////////////////////////////////////////////////// - public static void putCharSB(byte[] val, int index, int c) { + static void putCharSB(byte[] val, int index, int c) { checkIndex(index, val); putChar(val, index, c); } - public static void putCharsSB(byte[] val, int index, char[] ca, int off, int end) { + static void putCharsSB(byte[] val, int index, char[] ca, int off, int end) { checkBoundsBeginEnd(index, index + end - off, val); String.checkBoundsBeginEnd(off, end, ca.length); Unsafe.getUnsafe().copyMemory( @@ -1499,26 +1498,26 @@ final class StringUTF16 { (long) (end - off) << 1); } - public static void putCharsSB(byte[] val, int index, CharSequence s, int off, int end) { + static void putCharsSB(byte[] val, int index, CharSequence s, int off, int end) { checkBoundsBeginEnd(index, index + end - off, val); for (int i = off; i < end; i++) { putChar(val, index++, s.charAt(i)); } } - public static int codePointAtSB(byte[] val, int index, int end) { + static int codePointAtSB(byte[] val, int index, int end) { return codePointAt(val, index, end, true /* checked */); } - public static int codePointBeforeSB(byte[] val, int index) { + static int codePointBeforeSB(byte[] val, int index) { return codePointBefore(val, index, true /* checked */); } - public static int codePointCountSB(byte[] val, int beginIndex, int endIndex) { + static int codePointCountSB(byte[] val, int beginIndex, int endIndex) { return codePointCount(val, beginIndex, endIndex, true /* checked */); } - public static boolean contentEquals(byte[] v1, byte[] v2, int len) { + static boolean contentEquals(byte[] v1, byte[] v2, int len) { checkBoundsOffCount(0, len, v2); for (int i = 0; i < len; i++) { if ((char)(v1[i] & 0xff) != getChar(v2, i)) { @@ -1528,7 +1527,7 @@ final class StringUTF16 { return true; } - public static boolean contentEquals(byte[] value, CharSequence cs, int len) { + static boolean contentEquals(byte[] value, CharSequence cs, int len) { checkOffset(len, value); for (int i = 0; i < len; i++) { if (getChar(value, i) != cs.charAt(i)) { @@ -1538,7 +1537,7 @@ final class StringUTF16 { return true; } - public static void putCharsAt(byte[] value, int i, char c1, char c2, char c3, char c4) { + static void putCharsAt(byte[] value, int i, char c1, char c2, char c3, char c4) { int end = i + 4; checkBoundsBeginEnd(i, end, value); putChar(value, i, c1); @@ -1547,7 +1546,7 @@ final class StringUTF16 { putChar(value, i + 3, c4); } - public static void putCharsAt(byte[] value, int i, char c1, char c2, char c3, char c4, char c5) { + static void putCharsAt(byte[] value, int i, char c1, char c2, char c3, char c4, char c5) { int end = i + 5; checkBoundsBeginEnd(i, end, value); putChar(value, i, c1); @@ -1557,12 +1556,12 @@ final class StringUTF16 { putChar(value, i + 4, c5); } - public static char charAt(byte[] value, int index) { + static char charAt(byte[] value, int index) { checkIndex(index, value); return getChar(value, index); } - public static void reverse(byte[] val, int count) { + static void reverse(byte[] val, int count) { checkOffset(count, val); int n = count - 1; boolean hasSurrogates = false; @@ -1597,7 +1596,7 @@ final class StringUTF16 { } // inflatedCopy byte[] -> byte[] - public static void inflate(byte[] src, int srcOff, byte[] dst, int dstOff, int len) { + static void inflate(byte[] src, int srcOff, byte[] dst, int dstOff, int len) { // We need a range check here because 'putChar' has no checks checkBoundsOffCount(dstOff, len, dst); for (int i = 0; i < len; i++) { @@ -1606,7 +1605,7 @@ final class StringUTF16 { } // srcCoder == UTF16 && tgtCoder == LATIN1 - public static int lastIndexOfLatin1(byte[] src, int srcCount, + static int lastIndexOfLatin1(byte[] src, int srcCount, byte[] tgt, int tgtCount, int fromIndex) { assert fromIndex >= 0; assert tgtCount > 0; @@ -1659,19 +1658,19 @@ final class StringUTF16 { static final int MAX_LENGTH = Integer.MAX_VALUE >> 1; - public static void checkIndex(int off, byte[] val) { + static void checkIndex(int off, byte[] val) { String.checkIndex(off, length(val)); } - public static void checkOffset(int off, byte[] val) { + static void checkOffset(int off, byte[] val) { String.checkOffset(off, length(val)); } - public static void checkBoundsBeginEnd(int begin, int end, byte[] val) { + static void checkBoundsBeginEnd(int begin, int end, byte[] val) { String.checkBoundsBeginEnd(begin, end, length(val)); } - public static void checkBoundsOffCount(int offset, int count, byte[] val) { + static void checkBoundsOffCount(int offset, int count, byte[] val) { String.checkBoundsOffCount(offset, count, length(val)); } From 837f634bf29fd877dd62a2e0f7d7a1bd383372d3 Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Fri, 3 Oct 2025 21:11:33 +0000 Subject: [PATCH 0059/1639] 8369128: ProblemList jdk/jfr/event/profiling/TestCPUTimeSampleQueueAutoSizes.java in Xcomp configs 8369132: Disable vmTestbase/gc/vector/CircularListLow and LinearListLow with SerialGC 8369133: Disable gc/g1/TestShrinkAuxiliaryDataRunner.java with UseLargePages option Reviewed-by: ayang, dholmes --- test/hotspot/jtreg/gc/g1/TestShrinkAuxiliaryDataRunner.java | 1 + .../vmTestbase/gc/vector/CircularListLow/TestDescription.java | 1 + .../vmTestbase/gc/vector/LinearListLow/TestDescription.java | 1 + test/jdk/ProblemList-Xcomp.txt | 1 + 4 files changed, 4 insertions(+) diff --git a/test/hotspot/jtreg/gc/g1/TestShrinkAuxiliaryDataRunner.java b/test/hotspot/jtreg/gc/g1/TestShrinkAuxiliaryDataRunner.java index 309ba722787..d478f811490 100644 --- a/test/hotspot/jtreg/gc/g1/TestShrinkAuxiliaryDataRunner.java +++ b/test/hotspot/jtreg/gc/g1/TestShrinkAuxiliaryDataRunner.java @@ -29,6 +29,7 @@ package gc.g1; * @bug 8038423 8061715 * @summary Checks that decommitment occurs for JVM with different ObjectAlignmentInBytes values * @requires vm.gc.G1 + * @requires !vm.opt.final.UseLargePages * @library /test/lib * @library / * @modules java.base/jdk.internal.misc diff --git a/test/hotspot/jtreg/vmTestbase/gc/vector/CircularListLow/TestDescription.java b/test/hotspot/jtreg/vmTestbase/gc/vector/CircularListLow/TestDescription.java index 68fe6779e99..252e3a2d40f 100644 --- a/test/hotspot/jtreg/vmTestbase/gc/vector/CircularListLow/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/gc/vector/CircularListLow/TestDescription.java @@ -31,5 +31,6 @@ * * @library /vmTestbase * /test/lib + * @requires vm.gc != "Serial" * @run main/othervm/timeout=480 gc.vector.SimpleGC.SimpleGC -ms low -gp circularList(low) */ diff --git a/test/hotspot/jtreg/vmTestbase/gc/vector/LinearListLow/TestDescription.java b/test/hotspot/jtreg/vmTestbase/gc/vector/LinearListLow/TestDescription.java index 8ae86af035d..bd094045abf 100644 --- a/test/hotspot/jtreg/vmTestbase/gc/vector/LinearListLow/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/gc/vector/LinearListLow/TestDescription.java @@ -31,5 +31,6 @@ * * @library /vmTestbase * /test/lib + * @requires vm.gc != "Serial" * @run main/othervm gc.vector.SimpleGC.SimpleGC -ms low -gp linearList(low) */ diff --git a/test/jdk/ProblemList-Xcomp.txt b/test/jdk/ProblemList-Xcomp.txt index 5ed171a1fea..8e37e6e15d0 100644 --- a/test/jdk/ProblemList-Xcomp.txt +++ b/test/jdk/ProblemList-Xcomp.txt @@ -29,3 +29,4 @@ java/lang/invoke/MethodHandles/CatchExceptionTest.java 8146623 generic-all java/lang/reflect/callerCache/ReflectionCallerCacheTest.java 8332028 generic-all +jdk/jfr/event/profiling/TestCPUTimeSampleQueueAutoSizes.java 8367302 linux-all From e6868c624851d5c6bd182e45ba908cb06b731e8c Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Fri, 3 Oct 2025 22:17:01 +0000 Subject: [PATCH 0060/1639] 8369138: New test compiler/loopstripmining/MissingStoreAfterOuterStripMinedLoop.java fails Reviewed-by: kvn --- .../MissingStoreAfterOuterStripMinedLoop.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/hotspot/jtreg/compiler/loopstripmining/MissingStoreAfterOuterStripMinedLoop.java b/test/hotspot/jtreg/compiler/loopstripmining/MissingStoreAfterOuterStripMinedLoop.java index 8fa6cae12e6..24e3c4a5d30 100644 --- a/test/hotspot/jtreg/compiler/loopstripmining/MissingStoreAfterOuterStripMinedLoop.java +++ b/test/hotspot/jtreg/compiler/loopstripmining/MissingStoreAfterOuterStripMinedLoop.java @@ -29,7 +29,8 @@ * leading to wrong results. * * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation - * -Xcomp -XX:-UseLoopPredicate -XX:-UseAutoVectorizationPredicate + * -Xcomp -XX:-UseLoopPredicate + * -XX:+UnlockDiagnosticVMOptions -XX:-UseAutoVectorizationPredicate * -XX:CompileCommand=compileonly,compiler.loopstripmining.MissingStoreAfterOuterStripMinedLoop::test* * compiler.loopstripmining.MissingStoreAfterOuterStripMinedLoop * @run main compiler.loopstripmining.MissingStoreAfterOuterStripMinedLoop @@ -133,4 +134,4 @@ public class MissingStoreAfterOuterStripMinedLoop { throw new RuntimeException("unexpected value: " + a1.field + " " + a2.field + " " + a3.field); } } -} \ No newline at end of file +} From c3fbbfabcc9a9535a3b422c1c9afaa8e092a5da0 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Fri, 3 Oct 2025 23:16:41 +0000 Subject: [PATCH 0061/1639] 8369027: Apply java.io.Serial annotations in java.scripting Reviewed-by: rriggs --- .../share/classes/javax/script/ScriptException.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/java.scripting/share/classes/javax/script/ScriptException.java b/src/java.scripting/share/classes/javax/script/ScriptException.java index 1037ccde27f..48fb3221914 100644 --- a/src/java.scripting/share/classes/javax/script/ScriptException.java +++ b/src/java.scripting/share/classes/javax/script/ScriptException.java @@ -25,6 +25,8 @@ package javax.script; +import java.io.Serial; + /** * The generic Exception class for the Scripting APIs. Checked * exception types thrown by underlying scripting implementations must be wrapped in instances of @@ -36,6 +38,7 @@ package javax.script; */ public class ScriptException extends Exception { + @Serial private static final long serialVersionUID = 8265071037049225001L; /** @serial */ From 76dba201fa1a525780677e4d3dee8e9ffafd1cd7 Mon Sep 17 00:00:00 2001 From: Jaikiran Pai Date: Sat, 4 Oct 2025 08:09:09 +0000 Subject: [PATCH 0062/1639] 8368821: Test java/net/httpclient/http3/GetHTTP3Test.java intermittently fails with java.io.IOException: QUIC endpoint closed Reviewed-by: dfuchs --- test/jdk/java/net/httpclient/http3/GetHTTP3Test.java | 12 ++++++------ .../jdk/java/net/httpclient/http3/PostHTTP3Test.java | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/test/jdk/java/net/httpclient/http3/GetHTTP3Test.java b/test/jdk/java/net/httpclient/http3/GetHTTP3Test.java index a67710c485f..14842d401fd 100644 --- a/test/jdk/java/net/httpclient/http3/GetHTTP3Test.java +++ b/test/jdk/java/net/httpclient/http3/GetHTTP3Test.java @@ -33,7 +33,6 @@ import java.net.http.HttpOption.Http3DiscoveryMode; import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodyHandlers; import java.nio.charset.StandardCharsets; -import java.time.Duration; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -47,6 +46,7 @@ import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicLong; import javax.net.ssl.SSLContext; +import jdk.test.lib.Utils; import jdk.test.lib.net.SimpleSSLContext; import jdk.httpclient.test.lib.common.HttpServerAdapters; import jdk.httpclient.test.lib.http2.Http2TestServer; @@ -74,8 +74,9 @@ import static java.lang.System.out; * @library /test/lib /test/jdk/java/net/httpclient/lib * @build jdk.test.lib.net.SimpleSSLContext * jdk.httpclient.test.lib.common.HttpServerAdapters + * jdk.test.lib.Utils * @compile ../ReferenceTracker.java - * @run testng/othervm/timeout=60 -Djdk.internal.httpclient.debug=true + * @run testng/othervm -Djdk.internal.httpclient.debug=true * -Djdk.httpclient.HttpClient.log=requests,responses,errors * GetHTTP3Test * @summary Basic HTTP/3 GET test @@ -216,7 +217,6 @@ public class GetHTTP3Test implements HttpServerAdapters { .proxy(HttpClient.Builder.NO_PROXY) .executor(executor) .sslContext(sslContext) - .connectTimeout(Duration.ofSeconds(10)) .build(); return TRACKER.track(client); } @@ -348,7 +348,7 @@ public class GetHTTP3Test implements HttpServerAdapters { var tracker = TRACKER.getTracker(client); client = null; System.gc(); - AssertionError error = TRACKER.check(tracker, 1000); + AssertionError error = TRACKER.check(tracker, Utils.adjustTimeout(1000)); if (error != null) throw error; } System.out.println("test: DONE"); @@ -394,7 +394,7 @@ public class GetHTTP3Test implements HttpServerAdapters { var tracker = TRACKER.getTracker(client); client = null; System.gc(); - AssertionError error = TRACKER.check(tracker, 1000); + AssertionError error = TRACKER.check(tracker, Utils.adjustTimeout(1000)); if (error != null) throw error; } @@ -423,7 +423,7 @@ public class GetHTTP3Test implements HttpServerAdapters { sharedClient == null ? null : sharedClient.toString(); sharedClient = null; Thread.sleep(100); - AssertionError fail = TRACKER.check(500); + AssertionError fail = TRACKER.check(Utils.adjustTimeout(1000)); try { h3TestServer.stop(); } finally { diff --git a/test/jdk/java/net/httpclient/http3/PostHTTP3Test.java b/test/jdk/java/net/httpclient/http3/PostHTTP3Test.java index 0e7a57ca699..8bb6515d4ff 100644 --- a/test/jdk/java/net/httpclient/http3/PostHTTP3Test.java +++ b/test/jdk/java/net/httpclient/http3/PostHTTP3Test.java @@ -38,7 +38,6 @@ import java.net.http.HttpOption.Http3DiscoveryMode; import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodyHandlers; import java.nio.charset.StandardCharsets; -import java.time.Duration; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -53,6 +52,7 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.stream.Stream; import javax.net.ssl.SSLContext; +import jdk.test.lib.Utils; import jdk.test.lib.net.SimpleSSLContext; import jdk.httpclient.test.lib.common.HttpServerAdapters; import jdk.httpclient.test.lib.http2.Http2TestServer; @@ -79,6 +79,7 @@ import static java.lang.System.out; * @library /test/lib /test/jdk/java/net/httpclient/lib * @build jdk.test.lib.net.SimpleSSLContext * jdk.httpclient.test.lib.common.HttpServerAdapters + * jdk.test.lib.Utils * @compile ../ReferenceTracker.java * @run testng/othervm -Djdk.internal.httpclient.debug=true * -Djdk.httpclient.HttpClient.log=requests,responses,errors @@ -221,7 +222,6 @@ public class PostHTTP3Test implements HttpServerAdapters { .proxy(HttpClient.Builder.NO_PROXY) .executor(executor) .sslContext(sslContext) - .connectTimeout(Duration.ofSeconds(10)) .build(); return TRACKER.track(client); } @@ -375,7 +375,7 @@ public class PostHTTP3Test implements HttpServerAdapters { var tracker = TRACKER.getTracker(client); client = null; System.gc(); - AssertionError error = TRACKER.check(tracker, 1000); + AssertionError error = TRACKER.check(tracker, Utils.adjustTimeout(1000)); if (error != null) throw error; } System.out.println("test: DONE"); @@ -437,7 +437,7 @@ public class PostHTTP3Test implements HttpServerAdapters { var tracker = TRACKER.getTracker(client); client = null; System.gc(); - AssertionError error = TRACKER.check(tracker, 1000); + AssertionError error = TRACKER.check(tracker, Utils.adjustTimeout(1000)); if (error != null) throw error; } @@ -466,7 +466,7 @@ public class PostHTTP3Test implements HttpServerAdapters { sharedClient == null ? null : sharedClient.toString(); sharedClient = null; Thread.sleep(100); - AssertionError fail = TRACKER.check(500); + AssertionError fail = TRACKER.check(Utils.adjustTimeout(1000)); try { h3TestServer.stop(); } finally { From f740cd2aad43a008da1ed1ff15ebe2c790f893a0 Mon Sep 17 00:00:00 2001 From: Chad Rakoczy Date: Sat, 4 Oct 2025 21:17:26 +0000 Subject: [PATCH 0063/1639] 8316694: Implement relocation of nmethod within CodeCache Reviewed-by: kvn, eosterlund, never, eastigeevich, bulasevich --- src/hotspot/cpu/aarch64/relocInfo_aarch64.cpp | 1 - src/hotspot/share/code/codeBehaviours.cpp | 11 +- src/hotspot/share/code/codeBehaviours.hpp | 12 +- src/hotspot/share/code/codeCache.hpp | 2 +- src/hotspot/share/code/compiledIC.cpp | 4 +- src/hotspot/share/code/compiledIC.hpp | 2 +- src/hotspot/share/code/nmethod.cpp | 311 +++++++++++++++++- src/hotspot/share/code/nmethod.hpp | 24 +- src/hotspot/share/code/relocInfo.cpp | 3 +- src/hotspot/share/compiler/oopMap.cpp | 6 + src/hotspot/share/compiler/oopMap.hpp | 2 + .../share/gc/shenandoah/shenandoahUnload.cpp | 2 +- src/hotspot/share/gc/z/zUnload.cpp | 2 +- src/hotspot/share/jvmci/jvmciRuntime.hpp | 5 + src/hotspot/share/prims/whitebox.cpp | 58 +++- src/hotspot/share/runtime/globals.hpp | 3 + .../classes/sun/jvm/hotspot/code/NMethod.java | 43 +-- .../whitebox/CompilerWhiteBoxTest.java | 56 +++- .../whitebox/DeoptimizeRelocatedNMethod.java | 157 +++++++++ .../compiler/whitebox/RelocateNMethod.java | 146 ++++++++ .../RelocateNMethodMultiplePaths.java | 261 +++++++++++++++ .../whitebox/StressNMethodRelocation.java | 239 ++++++++++++++ .../NMethodRelocationTest.java | 178 ++++++++++ .../libNMethodRelocationTest.cpp | 114 +++++++ test/lib/jdk/test/whitebox/WhiteBox.java | 6 + test/lib/jdk/test/whitebox/code/CodeBlob.java | 7 +- 26 files changed, 1591 insertions(+), 64 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/whitebox/DeoptimizeRelocatedNMethod.java create mode 100644 test/hotspot/jtreg/compiler/whitebox/RelocateNMethod.java create mode 100644 test/hotspot/jtreg/compiler/whitebox/RelocateNMethodMultiplePaths.java create mode 100644 test/hotspot/jtreg/compiler/whitebox/StressNMethodRelocation.java create mode 100644 test/hotspot/jtreg/serviceability/jvmti/NMethodRelocation/NMethodRelocationTest.java create mode 100644 test/hotspot/jtreg/serviceability/jvmti/NMethodRelocation/libNMethodRelocationTest.cpp diff --git a/src/hotspot/cpu/aarch64/relocInfo_aarch64.cpp b/src/hotspot/cpu/aarch64/relocInfo_aarch64.cpp index f5d7d9e4387..94694b58d2f 100644 --- a/src/hotspot/cpu/aarch64/relocInfo_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/relocInfo_aarch64.cpp @@ -90,7 +90,6 @@ void Relocation::pd_set_call_destination(address x) { void trampoline_stub_Relocation::pd_fix_owner_after_move() { NativeCall* call = nativeCall_at(owner()); - assert(call->raw_destination() == owner(), "destination should be empty"); address trampoline = addr(); address dest = nativeCallTrampolineStub_at(trampoline)->destination(); if (!Assembler::reachable_from_branch_at(owner(), dest)) { diff --git a/src/hotspot/share/code/codeBehaviours.cpp b/src/hotspot/share/code/codeBehaviours.cpp index 1f9eb0e2914..bc5a81c95b3 100644 --- a/src/hotspot/share/code/codeBehaviours.cpp +++ b/src/hotspot/share/code/codeBehaviours.cpp @@ -23,23 +23,24 @@ */ #include "code/codeBehaviours.hpp" +#include "code/nmethod.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/safepoint.hpp" CompiledICProtectionBehaviour* CompiledICProtectionBehaviour::_current = nullptr; -bool DefaultICProtectionBehaviour::lock(nmethod* method) { - if (is_safe(method)) { +bool DefaultICProtectionBehaviour::lock(nmethod* nm) { + if (is_safe(nm)) { return false; } CompiledIC_lock->lock_without_safepoint_check(); return true; } -void DefaultICProtectionBehaviour::unlock(nmethod* method) { +void DefaultICProtectionBehaviour::unlock(nmethod* nm) { CompiledIC_lock->unlock(); } -bool DefaultICProtectionBehaviour::is_safe(nmethod* method) { - return SafepointSynchronize::is_at_safepoint() || CompiledIC_lock->owned_by_self(); +bool DefaultICProtectionBehaviour::is_safe(nmethod* nm) { + return SafepointSynchronize::is_at_safepoint() || CompiledIC_lock->owned_by_self() || (NMethodState_lock->owned_by_self() && nm->is_not_installed()); } diff --git a/src/hotspot/share/code/codeBehaviours.hpp b/src/hotspot/share/code/codeBehaviours.hpp index 0350f5752f6..96a38fffc30 100644 --- a/src/hotspot/share/code/codeBehaviours.hpp +++ b/src/hotspot/share/code/codeBehaviours.hpp @@ -33,18 +33,18 @@ class CompiledICProtectionBehaviour { static CompiledICProtectionBehaviour* _current; public: - virtual bool lock(nmethod* method) = 0; - virtual void unlock(nmethod* method) = 0; - virtual bool is_safe(nmethod* method) = 0; + virtual bool lock(nmethod* nm) = 0; + virtual void unlock(nmethod* nm) = 0; + virtual bool is_safe(nmethod* nm) = 0; static CompiledICProtectionBehaviour* current() { return _current; } static void set_current(CompiledICProtectionBehaviour* current) { _current = current; } }; class DefaultICProtectionBehaviour: public CompiledICProtectionBehaviour, public CHeapObj { - virtual bool lock(nmethod* method); - virtual void unlock(nmethod* method); - virtual bool is_safe(nmethod* method); + virtual bool lock(nmethod* nm); + virtual void unlock(nmethod* nm); + virtual bool is_safe(nmethod* nm); }; #endif // SHARE_CODE_CODEBEHAVIOURS_HPP diff --git a/src/hotspot/share/code/codeCache.hpp b/src/hotspot/share/code/codeCache.hpp index 3e446ab8430..dc9e5d7dc20 100644 --- a/src/hotspot/share/code/codeCache.hpp +++ b/src/hotspot/share/code/codeCache.hpp @@ -259,7 +259,7 @@ class CodeCache : AllStatic { static bool heap_available(CodeBlobType code_blob_type); // Returns the CodeBlobType for the given nmethod - static CodeBlobType get_code_blob_type(nmethod* nm) { + static CodeBlobType get_code_blob_type(const nmethod* nm) { return get_code_heap(nm)->code_blob_type(); } diff --git a/src/hotspot/share/code/compiledIC.cpp b/src/hotspot/share/code/compiledIC.cpp index 03d9adc8e24..5f5c9711441 100644 --- a/src/hotspot/share/code/compiledIC.cpp +++ b/src/hotspot/share/code/compiledIC.cpp @@ -55,8 +55,8 @@ CompiledICLocker::~CompiledICLocker() { } } -bool CompiledICLocker::is_safe(nmethod* method) { - return CompiledICProtectionBehaviour::current()->is_safe(method); +bool CompiledICLocker::is_safe(nmethod* nm) { + return CompiledICProtectionBehaviour::current()->is_safe(nm); } bool CompiledICLocker::is_safe(address code) { diff --git a/src/hotspot/share/code/compiledIC.hpp b/src/hotspot/share/code/compiledIC.hpp index 624c1b428de..db8a0860b39 100644 --- a/src/hotspot/share/code/compiledIC.hpp +++ b/src/hotspot/share/code/compiledIC.hpp @@ -50,7 +50,7 @@ class CompiledICLocker: public StackObj { public: CompiledICLocker(nmethod* method); ~CompiledICLocker(); - static bool is_safe(nmethod* method); + static bool is_safe(nmethod* nm); static bool is_safe(address code); }; diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp index 1540fa0333a..7274b627f3e 100644 --- a/src/hotspot/share/code/nmethod.cpp +++ b/src/hotspot/share/code/nmethod.cpp @@ -754,7 +754,7 @@ Method* nmethod::attached_method_before_pc(address pc) { } void nmethod::clear_inline_caches() { - assert(SafepointSynchronize::is_at_safepoint(), "clearing of IC's only allowed at safepoint"); + assert(SafepointSynchronize::is_at_safepoint() || (NMethodState_lock->owned_by_self() && is_not_installed()), "clearing of IC's only allowed at safepoint or when not installed"); RelocIterator iter(this); while (iter.next()) { iter.reloc()->clear_inline_cache(); @@ -1146,7 +1146,8 @@ nmethod* nmethod::new_nmethod(const methodHandle& method, #if INCLUDE_JVMCI + align_up(speculations_len , oopSize) #endif - + align_up(debug_info->data_size() , oopSize); + + align_up(debug_info->data_size() , oopSize) + + align_up(ImmutableDataReferencesCounterSize, oopSize); // First, allocate space for immutable data in C heap. address immutable_data = nullptr; @@ -1371,10 +1372,266 @@ nmethod::nmethod( } } + +nmethod::nmethod(const nmethod &nm) : CodeBlob(nm._name, nm._kind, nm._size, nm._header_size) +{ + + if (nm._oop_maps != nullptr) { + _oop_maps = nm._oop_maps->clone(); + } else { + _oop_maps = nullptr; + } + + _size = nm._size; + _relocation_size = nm._relocation_size; + _content_offset = nm._content_offset; + _code_offset = nm._code_offset; + _data_offset = nm._data_offset; + _frame_size = nm._frame_size; + + S390_ONLY( _ctable_offset = nm._ctable_offset; ) + + _header_size = nm._header_size; + _frame_complete_offset = nm._frame_complete_offset; + + _kind = nm._kind; + + _caller_must_gc_arguments = nm._caller_must_gc_arguments; + +#ifndef PRODUCT + _asm_remarks.share(nm._asm_remarks); + _dbg_strings.share(nm._dbg_strings); +#endif + + // Allocate memory and copy mutable data to C heap + _mutable_data_size = nm._mutable_data_size; + if (_mutable_data_size > 0) { + _mutable_data = (address)os::malloc(_mutable_data_size, mtCode); + if (_mutable_data == nullptr) { + vm_exit_out_of_memory(_mutable_data_size, OOM_MALLOC_ERROR, "nmethod: no space for mutable data"); + } + memcpy(mutable_data_begin(), nm.mutable_data_begin(), nm.mutable_data_size()); + } else { + _mutable_data = nullptr; + } + + _deoptimization_generation = 0; + _gc_epoch = CodeCache::gc_epoch(); + _method = nm._method; + _osr_link = nullptr; + + // Increment number of references to immutable data to share it between nmethods + _immutable_data_size = nm._immutable_data_size; + if (_immutable_data_size > 0) { + _immutable_data = nm._immutable_data; + set_immutable_data_references_counter(get_immutable_data_references_counter() + 1); + } else { + _immutable_data = blob_end(); + } + + _exception_cache = nullptr; + _gc_data = nullptr; + _oops_do_mark_nmethods = nullptr; + _oops_do_mark_link = nullptr; + _compiled_ic_data = nullptr; + + if (nm._osr_entry_point != nullptr) { + _osr_entry_point = (nm._osr_entry_point - (address) &nm) + (address) this; + } else { + _osr_entry_point = nullptr; + } + + _entry_offset = nm._entry_offset; + _verified_entry_offset = nm._verified_entry_offset; + _entry_bci = nm._entry_bci; + + _skipped_instructions_size = nm._skipped_instructions_size; + _stub_offset = nm._stub_offset; + _exception_offset = nm._exception_offset; + _deopt_handler_offset = nm._deopt_handler_offset; + _unwind_handler_offset = nm._unwind_handler_offset; + _num_stack_arg_slots = nm._num_stack_arg_slots; + _oops_size = nm._oops_size; +#if INCLUDE_JVMCI + _metadata_size = nm._metadata_size; +#endif + _nul_chk_table_offset = nm._nul_chk_table_offset; + _handler_table_offset = nm._handler_table_offset; + _scopes_pcs_offset = nm._scopes_pcs_offset; + _scopes_data_offset = nm._scopes_data_offset; +#if INCLUDE_JVMCI + _speculations_offset = nm._speculations_offset; +#endif + + _orig_pc_offset = nm._orig_pc_offset; + _compile_id = nm._compile_id; + _comp_level = nm._comp_level; + _compiler_type = nm._compiler_type; + _is_unloading_state = nm._is_unloading_state; + _state = not_installed; + + _has_unsafe_access = nm._has_unsafe_access; + _has_wide_vectors = nm._has_wide_vectors; + _has_monitors = nm._has_monitors; + _has_scoped_access = nm._has_scoped_access; + _has_flushed_dependencies = nm._has_flushed_dependencies; + _is_unlinked = nm._is_unlinked; + _load_reported = nm._load_reported; + + _deoptimization_status = nm._deoptimization_status; + + if (nm._pc_desc_container != nullptr) { + _pc_desc_container = new PcDescContainer(scopes_pcs_begin()); + } else { + _pc_desc_container = nullptr; + } + + // Copy nmethod contents excluding header + // - Constant part (doubles, longs and floats used in nmethod) + // - Code part: + // - Code body + // - Exception handler + // - Stub code + // - OOP table + memcpy(consts_begin(), nm.consts_begin(), nm.data_end() - nm.consts_begin()); + + post_init(); +} + +nmethod* nmethod::relocate(CodeBlobType code_blob_type) { + assert(NMethodRelocation, "must enable use of function"); + + // Locks required to be held by caller to ensure the nmethod + // is not modified or purged from code cache during relocation + assert_lock_strong(CodeCache_lock); + assert_lock_strong(Compile_lock); + assert(CompiledICLocker::is_safe(this), "mt unsafe call"); + + if (!is_relocatable()) { + return nullptr; + } + + run_nmethod_entry_barrier(); + nmethod* nm_copy = new (size(), code_blob_type) nmethod(*this); + + if (nm_copy == nullptr) { + return nullptr; + } + + // Fix relocation + RelocIterator iter(nm_copy); + CodeBuffer src(this); + CodeBuffer dst(nm_copy); + while (iter.next()) { +#ifdef USE_TRAMPOLINE_STUB_FIX_OWNER + // Direct calls may no longer be in range and the use of a trampoline may now be required. + // Instead, allow trampoline relocations to update their owners and perform the necessary checks. + if (iter.reloc()->is_call()) { + address trampoline = trampoline_stub_Relocation::get_trampoline_for(iter.reloc()->addr(), nm_copy); + if (trampoline != nullptr) { + continue; + } + } +#endif + + iter.reloc()->fix_relocation_after_move(&src, &dst); + } + + // To make dependency checking during class loading fast, record + // the nmethod dependencies in the classes it is dependent on. + // This allows the dependency checking code to simply walk the + // class hierarchy above the loaded class, checking only nmethods + // which are dependent on those classes. The slow way is to + // check every nmethod for dependencies which makes it linear in + // the number of methods compiled. For applications with a lot + // classes the slow way is too slow. + for (Dependencies::DepStream deps(nm_copy); deps.next(); ) { + if (deps.type() == Dependencies::call_site_target_value) { + // CallSite dependencies are managed on per-CallSite instance basis. + oop call_site = deps.argument_oop(0); + MethodHandles::add_dependent_nmethod(call_site, nm_copy); + } else { + InstanceKlass* ik = deps.context_type(); + if (ik == nullptr) { + continue; // ignore things like evol_method + } + // record this nmethod as dependent on this klass + ik->add_dependent_nmethod(nm_copy); + } + } + + MutexLocker ml_NMethodState_lock(NMethodState_lock, Mutex::_no_safepoint_check_flag); + + // Verify the nm we copied from is still valid + if (!is_marked_for_deoptimization() && is_in_use()) { + assert(method() != nullptr && method()->code() == this, "should be if is in use"); + + nm_copy->clear_inline_caches(); + + // Attempt to start using the copy + if (nm_copy->make_in_use()) { + ICache::invalidate_range(nm_copy->code_begin(), nm_copy->code_size()); + + methodHandle mh(Thread::current(), nm_copy->method()); + nm_copy->method()->set_code(mh, nm_copy); + + make_not_used(); + + nm_copy->post_compiled_method_load_event(); + + nm_copy->log_relocated_nmethod(this); + + return nm_copy; + } + } + + nm_copy->make_not_used(); + + return nullptr; +} + +bool nmethod::is_relocatable() { + if (!is_java_method()) { + return false; + } + + if (!is_in_use()) { + return false; + } + + if (is_osr_method()) { + return false; + } + + if (is_marked_for_deoptimization()) { + return false; + } + +#if INCLUDE_JVMCI + if (jvmci_nmethod_data() != nullptr && jvmci_nmethod_data()->has_mirror()) { + return false; + } +#endif + + if (is_unloading()) { + return false; + } + + if (has_evol_metadata()) { + return false; + } + + return true; +} + void* nmethod::operator new(size_t size, int nmethod_size, int comp_level) throw () { return CodeCache::allocate(nmethod_size, CodeCache::get_code_blob_type(comp_level)); } +void* nmethod::operator new(size_t size, int nmethod_size, CodeBlobType code_blob_type) throw () { + return CodeCache::allocate(nmethod_size, code_blob_type); +} + void* nmethod::operator new(size_t size, int nmethod_size, bool allow_NonNMethod_space) throw () { // Try MethodNonProfiled and MethodProfiled. void* return_value = CodeCache::allocate(nmethod_size, CodeBlobType::MethodNonProfiled); @@ -1494,9 +1751,9 @@ nmethod::nmethod( #if INCLUDE_JVMCI _speculations_offset = _scopes_data_offset + align_up(debug_info->data_size(), oopSize); - DEBUG_ONLY( int immutable_data_end_offset = _speculations_offset + align_up(speculations_len, oopSize); ) + DEBUG_ONLY( int immutable_data_end_offset = _speculations_offset + align_up(speculations_len, oopSize) + align_up(ImmutableDataReferencesCounterSize, oopSize); ) #else - DEBUG_ONLY( int immutable_data_end_offset = _scopes_data_offset + align_up(debug_info->data_size(), oopSize); ) + DEBUG_ONLY( int immutable_data_end_offset = _scopes_data_offset + align_up(debug_info->data_size(), oopSize) + align_up(ImmutableDataReferencesCounterSize, oopSize); ) #endif assert(immutable_data_end_offset <= immutable_data_size, "wrong read-only data size: %d > %d", immutable_data_end_offset, immutable_data_size); @@ -1529,6 +1786,7 @@ nmethod::nmethod( memcpy(speculations_begin(), speculations, speculations_len); } #endif + set_immutable_data_references_counter(1); post_init(); @@ -1595,6 +1853,40 @@ void nmethod::log_new_nmethod() const { } } + +void nmethod::log_relocated_nmethod(nmethod* original) const { + if (LogCompilation && xtty != nullptr) { + ttyLocker ttyl; + xtty->begin_elem("relocated nmethod"); + log_identity(xtty); + xtty->print(" entry='" INTPTR_FORMAT "' size='%d'", p2i(code_begin()), size()); + + const char* original_code_heap_name = CodeCache::get_code_heap_name(CodeCache::get_code_blob_type(original)); + xtty->print(" original_address='" INTPTR_FORMAT "'", p2i(original)); + xtty->print(" original_code_heap='%s'", original_code_heap_name); + + const char* new_code_heap_name = CodeCache::get_code_heap_name(CodeCache::get_code_blob_type(this)); + xtty->print(" new_address='" INTPTR_FORMAT "'", p2i(this)); + xtty->print(" new_code_heap='%s'", new_code_heap_name); + + LOG_OFFSET(xtty, relocation); + LOG_OFFSET(xtty, consts); + LOG_OFFSET(xtty, insts); + LOG_OFFSET(xtty, stub); + LOG_OFFSET(xtty, scopes_data); + LOG_OFFSET(xtty, scopes_pcs); + LOG_OFFSET(xtty, dependencies); + LOG_OFFSET(xtty, handler_table); + LOG_OFFSET(xtty, nul_chk_table); + LOG_OFFSET(xtty, oops); + LOG_OFFSET(xtty, metadata); + + xtty->method(method()); + xtty->stamp(); + xtty->end_elem(); + } +} + #undef LOG_OFFSET @@ -2127,9 +2419,18 @@ void nmethod::purge(bool unregister_nmethod) { delete[] _compiled_ic_data; if (_immutable_data != blob_end()) { - os::free(_immutable_data); + int reference_count = get_immutable_data_references_counter(); + assert(reference_count > 0, "immutable data has no references"); + + set_immutable_data_references_counter(reference_count - 1); + // Free memory if this is the last nmethod referencing immutable data + if (reference_count == 0) { + os::free(_immutable_data); + } + _immutable_data = blob_end(); // Valid not null address } + if (unregister_nmethod) { Universe::heap()->unregister_nmethod(this); } diff --git a/src/hotspot/share/code/nmethod.hpp b/src/hotspot/share/code/nmethod.hpp index 1e876657098..2332766a47c 100644 --- a/src/hotspot/share/code/nmethod.hpp +++ b/src/hotspot/share/code/nmethod.hpp @@ -154,6 +154,7 @@ public: // - Scopes data array // - Scopes pcs array // - JVMCI speculations array +// - Nmethod reference counter #if INCLUDE_JVMCI class FailedSpeculation; @@ -167,6 +168,8 @@ class nmethod : public CodeBlob { friend class JVMCINMethodData; friend class DeoptimizationScope; + #define ImmutableDataReferencesCounterSize ((int)sizeof(int)) + private: // Used to track in which deoptimize handshake this method will be deoptimized. @@ -330,8 +333,11 @@ class nmethod : public CodeBlob { #endif ); + nmethod(const nmethod &nm); + // helper methods void* operator new(size_t size, int nmethod_size, int comp_level) throw(); + void* operator new(size_t size, int nmethod_size, CodeBlobType code_blob_type) throw(); // For method handle intrinsics: Try MethodNonProfiled, MethodProfiled and NonNMethod. // Attention: Only allow NonNMethod space for special nmethods which don't need to be @@ -564,6 +570,12 @@ public: #endif ); + // Relocate the nmethod to the code heap identified by code_blob_type. + // Returns nullptr if the code heap does not have enough space, the + // nmethod is unrelocatable, or the nmethod is invalidated during relocation, + // otherwise the relocated nmethod. The original nmethod will be marked not entrant. + nmethod* relocate(CodeBlobType code_blob_type); + static nmethod* new_native_nmethod(const methodHandle& method, int compile_id, CodeBuffer *code_buffer, @@ -580,6 +592,8 @@ public: bool is_java_method () const { return _method != nullptr && !_method->is_native(); } bool is_osr_method () const { return _entry_bci != InvocationEntryBci; } + bool is_relocatable(); + // Compiler task identification. Note that all OSR methods // are numbered in an independent sequence if CICountOSR is true, // and native method wrappers are also numbered independently if @@ -632,11 +646,13 @@ public: #if INCLUDE_JVMCI address scopes_data_end () const { return _immutable_data + _speculations_offset ; } address speculations_begin () const { return _immutable_data + _speculations_offset ; } - address speculations_end () const { return immutable_data_end(); } + address speculations_end () const { return immutable_data_end() - ImmutableDataReferencesCounterSize ; } #else - address scopes_data_end () const { return immutable_data_end(); } + address scopes_data_end () const { return immutable_data_end() - ImmutableDataReferencesCounterSize ; } #endif + address immutable_data_references_counter_begin () const { return immutable_data_end() - ImmutableDataReferencesCounterSize ; } + // Sizes int immutable_data_size() const { return _immutable_data_size; } int consts_size () const { return int( consts_end () - consts_begin ()); } @@ -946,6 +962,9 @@ public: bool load_reported() const { return _load_reported; } void set_load_reported() { _load_reported = true; } + inline int get_immutable_data_references_counter() { return *((int*)immutable_data_references_counter_begin()); } + inline void set_immutable_data_references_counter(int count) { *((int*)immutable_data_references_counter_begin()) = count; } + public: // ScopeDesc retrieval operation PcDesc* pc_desc_at(address pc) { return find_pc_desc(pc, false); } @@ -1014,6 +1033,7 @@ public: // Logging void log_identity(xmlStream* log) const; void log_new_nmethod() const; + void log_relocated_nmethod(nmethod* original) const; void log_state_change(InvalidationReason invalidation_reason) const; // Prints block-level comments, including nmethod specific block labels: diff --git a/src/hotspot/share/code/relocInfo.cpp b/src/hotspot/share/code/relocInfo.cpp index 8fc22596d01..02a1e5faf16 100644 --- a/src/hotspot/share/code/relocInfo.cpp +++ b/src/hotspot/share/code/relocInfo.cpp @@ -406,11 +406,12 @@ void CallRelocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer pd_set_call_destination(callee); } - #ifdef USE_TRAMPOLINE_STUB_FIX_OWNER void trampoline_stub_Relocation::fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest) { // Finalize owner destination only for nmethods if (dest->blob() != nullptr) return; + // We either relocate a nmethod residing in CodeCache or just generated code from CodeBuffer + assert(src->blob() == nullptr || nativeCall_at(owner())->raw_destination() == owner(), "destination should be empty"); pd_fix_owner_after_move(); } #endif diff --git a/src/hotspot/share/compiler/oopMap.cpp b/src/hotspot/share/compiler/oopMap.cpp index aa010872975..87467d06400 100644 --- a/src/hotspot/share/compiler/oopMap.cpp +++ b/src/hotspot/share/compiler/oopMap.cpp @@ -862,6 +862,12 @@ ImmutableOopMapSet* ImmutableOopMapSet::build_from(const OopMapSet* oopmap_set) return builder.build(); } +ImmutableOopMapSet* ImmutableOopMapSet::clone() const { + address buffer = NEW_C_HEAP_ARRAY(unsigned char, _size, mtCode); + memcpy(buffer, (address)this, _size); + return (ImmutableOopMapSet*)buffer; +} + void ImmutableOopMapSet::operator delete(void* p) { FREE_C_HEAP_ARRAY(unsigned char, p); } diff --git a/src/hotspot/share/compiler/oopMap.hpp b/src/hotspot/share/compiler/oopMap.hpp index ef8845ac9aa..f7a8cd8496c 100644 --- a/src/hotspot/share/compiler/oopMap.hpp +++ b/src/hotspot/share/compiler/oopMap.hpp @@ -348,6 +348,8 @@ public: static ImmutableOopMapSet* build_from(const OopMapSet* oopmap_set); + ImmutableOopMapSet* clone() const; + int find_slot_for_offset(int pc_offset) const; const ImmutableOopMap* find_map_at_offset(int pc_offset) const; const ImmutableOopMap* find_map_at_slot(int slot, int pc_offset) const; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahUnload.cpp b/src/hotspot/share/gc/shenandoah/shenandoahUnload.cpp index 83151313f75..b248fab7958 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahUnload.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahUnload.cpp @@ -103,7 +103,7 @@ public: } virtual bool is_safe(nmethod* nm) { - if (SafepointSynchronize::is_at_safepoint() || nm->is_unloading()) { + if (SafepointSynchronize::is_at_safepoint() || nm->is_unloading() || (NMethodState_lock->owned_by_self() && nm->is_not_installed())) { return true; } diff --git a/src/hotspot/share/gc/z/zUnload.cpp b/src/hotspot/share/gc/z/zUnload.cpp index c8b32385fcd..5c50b3077dd 100644 --- a/src/hotspot/share/gc/z/zUnload.cpp +++ b/src/hotspot/share/gc/z/zUnload.cpp @@ -100,7 +100,7 @@ public: } virtual bool is_safe(nmethod* nm) { - if (SafepointSynchronize::is_at_safepoint() || nm->is_unloading()) { + if (SafepointSynchronize::is_at_safepoint() || nm->is_unloading() || (NMethodState_lock->owned_by_self() && nm->is_not_installed())) { return true; } diff --git a/src/hotspot/share/jvmci/jvmciRuntime.hpp b/src/hotspot/share/jvmci/jvmciRuntime.hpp index f4c322e831c..885ff0dbf9b 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.hpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.hpp @@ -137,6 +137,11 @@ public: // Gets the JVMCI name of the nmethod (which may be null). const char* name() { return has_name() ? (char*)(((address) this) + sizeof(JVMCINMethodData)) : nullptr; } + // Returns true if this nmethod has a mirror + bool has_mirror() const { + return _nmethod_mirror_index != -1; + } + // Clears the HotSpotNmethod.address field in the mirror. If nm // is dead, the HotSpotNmethod.entryPoint field is also cleared. void invalidate_nmethod_mirror(nmethod* nm, nmethod::InvalidationReason invalidation_reason); diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp index f77b648ba95..1ecd105f218 100644 --- a/src/hotspot/share/prims/whitebox.cpp +++ b/src/hotspot/share/prims/whitebox.cpp @@ -39,6 +39,7 @@ #include "classfile/systemDictionary.hpp" #include "classfile/vmSymbols.hpp" #include "code/codeCache.hpp" +#include "code/compiledIC.hpp" #include "compiler/compilationPolicy.hpp" #include "compiler/compilerOracle.hpp" #include "compiler/directivesParser.hpp" @@ -1548,19 +1549,23 @@ struct CodeBlobStub { name(os::strdup(blob->name())), size(blob->size()), blob_type(static_cast(WhiteBox::get_blob_type(blob))), - address((jlong) blob) { } + address((jlong) blob), + code_begin((jlong) blob->code_begin()), + is_nmethod((jboolean) blob->is_nmethod()) { } ~CodeBlobStub() { os::free((void*) name); } const char* const name; const jint size; const jint blob_type; const jlong address; + const jlong code_begin; + const jboolean is_nmethod; }; static jobjectArray codeBlob2objectArray(JavaThread* thread, JNIEnv* env, CodeBlobStub* cb) { ResourceMark rm; jclass clazz = env->FindClass(vmSymbols::java_lang_Object()->as_C_string()); CHECK_JNI_EXCEPTION_(env, nullptr); - jobjectArray result = env->NewObjectArray(4, clazz, nullptr); + jobjectArray result = env->NewObjectArray(6, clazz, nullptr); jstring name = env->NewStringUTF(cb->name); CHECK_JNI_EXCEPTION_(env, nullptr); @@ -1578,6 +1583,14 @@ static jobjectArray codeBlob2objectArray(JavaThread* thread, JNIEnv* env, CodeBl CHECK_JNI_EXCEPTION_(env, nullptr); env->SetObjectArrayElement(result, 3, obj); + obj = longBox(thread, env, cb->code_begin); + CHECK_JNI_EXCEPTION_(env, nullptr); + env->SetObjectArrayElement(result, 4, obj); + + obj = booleanBox(thread, env, cb->is_nmethod); + CHECK_JNI_EXCEPTION_(env, nullptr); + env->SetObjectArrayElement(result, 5, obj); + return result; } @@ -1627,6 +1640,44 @@ WB_ENTRY(jobjectArray, WB_GetNMethod(JNIEnv* env, jobject o, jobject method, jbo return result; WB_END +WB_ENTRY(void, WB_RelocateNMethodFromMethod(JNIEnv* env, jobject o, jobject method, jint blob_type)) + ResourceMark rm(THREAD); + jmethodID jmid = reflected_method_to_jmid(thread, env, method); + CHECK_JNI_EXCEPTION(env); + methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); + nmethod* code = mh->code(); + if (code != nullptr) { + MutexLocker ml_Compile_lock(Compile_lock); + CompiledICLocker ic_locker(code); + MutexLocker ml_CodeCache_lock(CodeCache_lock, Mutex::_no_safepoint_check_flag); + code->relocate(static_cast(blob_type)); + } +WB_END + +WB_ENTRY(void, WB_RelocateNMethodFromAddr(JNIEnv* env, jobject o, jlong addr, jint blob_type)) + ResourceMark rm(THREAD); + CHECK_JNI_EXCEPTION(env); + void* address = (void*) addr; + + if (address == nullptr) { + return; + } + + MutexLocker ml_Compile_lock(Compile_lock); + MutexLocker ml_CompiledIC_lock(CompiledIC_lock, Mutex::_no_safepoint_check_flag); + MutexLocker ml_CodeCache_lock(CodeCache_lock, Mutex::_no_safepoint_check_flag); + + // Verify that nmethod address is still valid + CodeBlob* blob = CodeCache::find_blob(address); + if (blob != nullptr && blob->is_nmethod()) { + nmethod* code = blob->as_nmethod(); + if (code->is_in_use()) { + CompiledICLocker ic_locker(code); + code->relocate(static_cast(blob_type)); + } + } +WB_END + CodeBlob* WhiteBox::allocate_code_blob(int size, CodeBlobType blob_type) { guarantee(WhiteBoxAPI, "internal testing API :: WhiteBox has to be enabled"); BufferBlob* blob; @@ -2916,6 +2967,9 @@ static JNINativeMethod methods[] = { {CC"getCPUFeatures", CC"()Ljava/lang/String;", (void*)&WB_GetCPUFeatures }, {CC"getNMethod0", CC"(Ljava/lang/reflect/Executable;Z)[Ljava/lang/Object;", (void*)&WB_GetNMethod }, + {CC"relocateNMethodFromMethod0", CC"(Ljava/lang/reflect/Executable;I)V", + (void*)&WB_RelocateNMethodFromMethod }, + {CC"relocateNMethodFromAddr", CC"(JI)V", (void*)&WB_RelocateNMethodFromAddr }, {CC"allocateCodeBlob", CC"(II)J", (void*)&WB_AllocateCodeBlob }, {CC"freeCodeBlob", CC"(J)V", (void*)&WB_FreeCodeBlob }, {CC"getCodeHeapEntries", CC"(I)[Ljava/lang/Object;",(void*)&WB_GetCodeHeapEntries }, diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index dac01d018bf..513edaf6588 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -1565,6 +1565,9 @@ const int ObjectAlignmentInBytes = 8; "Start aggressive sweeping if less than X[%] of the total code cache is free.")\ range(0, 100) \ \ + product(bool, NMethodRelocation, false, EXPERIMENTAL, \ + "Enables use of experimental function nmethod::relocate()") \ + \ /* interpreter debugging */ \ develop(intx, BinarySwitchThreshold, 5, \ "Minimal number of lookupswitch entries for rewriting to binary " \ diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/NMethod.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/NMethod.java index c8ba2e8b5af..939b47fdd2a 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/NMethod.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/NMethod.java @@ -37,6 +37,7 @@ import sun.jvm.hotspot.utilities.Observer; public class NMethod extends CodeBlob { private static long pcDescSize; + private static long immutableDataReferencesCounterSize; private static AddressField methodField; /** != InvocationEntryBci if this nmethod is an on-stack replacement method */ private static CIntegerField entryBCIField; @@ -78,24 +79,25 @@ public class NMethod extends CodeBlob { private static void initialize(TypeDataBase db) { Type type = db.lookupType("nmethod"); - methodField = type.getAddressField("_method"); - entryBCIField = type.getCIntegerField("_entry_bci"); - osrLinkField = type.getAddressField("_osr_link"); - immutableDataField = type.getAddressField("_immutable_data"); - immutableDataSizeField = type.getCIntegerField("_immutable_data_size"); - exceptionOffsetField = type.getCIntegerField("_exception_offset"); - deoptHandlerOffsetField = type.getCIntegerField("_deopt_handler_offset"); - origPCOffsetField = type.getCIntegerField("_orig_pc_offset"); - stubOffsetField = type.getCIntegerField("_stub_offset"); - scopesPCsOffsetField = type.getCIntegerField("_scopes_pcs_offset"); - scopesDataOffsetField = type.getCIntegerField("_scopes_data_offset"); - handlerTableOffsetField = new CIntField(type.getCIntegerField("_handler_table_offset"), 0); - nulChkTableOffsetField = new CIntField(type.getCIntegerField("_nul_chk_table_offset"), 0); - entryOffsetField = new CIntField(type.getCIntegerField("_entry_offset"), 0); - verifiedEntryOffsetField = new CIntField(type.getCIntegerField("_verified_entry_offset"), 0); - osrEntryPointField = type.getAddressField("_osr_entry_point"); - compLevelField = new CIntField(type.getCIntegerField("_comp_level"), 0); - pcDescSize = db.lookupType("PcDesc").getSize(); + methodField = type.getAddressField("_method"); + entryBCIField = type.getCIntegerField("_entry_bci"); + osrLinkField = type.getAddressField("_osr_link"); + immutableDataField = type.getAddressField("_immutable_data"); + immutableDataSizeField = type.getCIntegerField("_immutable_data_size"); + exceptionOffsetField = type.getCIntegerField("_exception_offset"); + deoptHandlerOffsetField = type.getCIntegerField("_deopt_handler_offset"); + origPCOffsetField = type.getCIntegerField("_orig_pc_offset"); + stubOffsetField = type.getCIntegerField("_stub_offset"); + scopesPCsOffsetField = type.getCIntegerField("_scopes_pcs_offset"); + scopesDataOffsetField = type.getCIntegerField("_scopes_data_offset"); + handlerTableOffsetField = new CIntField(type.getCIntegerField("_handler_table_offset"), 0); + nulChkTableOffsetField = new CIntField(type.getCIntegerField("_nul_chk_table_offset"), 0); + entryOffsetField = new CIntField(type.getCIntegerField("_entry_offset"), 0); + verifiedEntryOffsetField = new CIntField(type.getCIntegerField("_verified_entry_offset"), 0); + osrEntryPointField = type.getAddressField("_osr_entry_point"); + compLevelField = new CIntField(type.getCIntegerField("_comp_level"), 0); + pcDescSize = db.lookupType("PcDesc").getSize(); + immutableDataReferencesCounterSize = VM.getVM().getIntSize(); } public NMethod(Address addr) { @@ -139,7 +141,7 @@ public class NMethod extends CodeBlob { public Address scopesDataBegin() { return immutableDataBegin().addOffsetTo(getScopesDataOffset()); } public Address scopesDataEnd() { return immutableDataBegin().addOffsetTo(getScopesPCsOffset()); } public Address scopesPCsBegin() { return immutableDataBegin().addOffsetTo(getScopesPCsOffset()); } - public Address scopesPCsEnd() { return immutableDataEnd(); } + public Address scopesPCsEnd() { return immutableDataEnd().addOffsetTo(-immutableDataReferencesCounterSize); } public Address metadataBegin() { return mutableDataBegin().addOffsetTo(getRelocationSize()); } public Address metadataEnd() { return mutableDataEnd(); } @@ -169,7 +171,8 @@ public class NMethod extends CodeBlob { scopesPCsSize() + dependenciesSize() + handlerTableSize() + - nulChkTableSize(); + nulChkTableSize() + + (int) immutableDataReferencesCounterSize; } public boolean constantsContains (Address addr) { return constantsBegin() .lessThanOrEqual(addr) && constantsEnd() .greaterThan(addr); } diff --git a/test/hotspot/jtreg/compiler/whitebox/CompilerWhiteBoxTest.java b/test/hotspot/jtreg/compiler/whitebox/CompilerWhiteBoxTest.java index f87292be019..eb0f70af5c4 100644 --- a/test/hotspot/jtreg/compiler/whitebox/CompilerWhiteBoxTest.java +++ b/test/hotspot/jtreg/compiler/whitebox/CompilerWhiteBoxTest.java @@ -221,15 +221,28 @@ public abstract class CompilerWhiteBoxTest { * compilation level. */ protected final void checkNotCompiled(boolean isOsr) { - if (WHITE_BOX.isMethodQueuedForCompilation(method)) { - throw new RuntimeException(method + " must not be in queue"); + checkNotCompiled(method, isOsr); + } + + /** + * Checks, that the specified executable is not (OSR-)compiled. + * + * @param executable The method or constructor to check. + * @param isOsr Check for OSR compilation if true + * @throws RuntimeException if {@linkplain #method} is in compiler queue or + * is compiled, or if {@linkplain #method} has zero + * compilation level. + */ + protected static final void checkNotCompiled(Executable executable, boolean isOsr) { + if (WHITE_BOX.isMethodQueuedForCompilation(executable)) { + throw new RuntimeException(executable + " must not be in queue"); } - if (WHITE_BOX.isMethodCompiled(method, isOsr)) { - throw new RuntimeException(method + " must not be " + + if (WHITE_BOX.isMethodCompiled(executable, isOsr)) { + throw new RuntimeException(executable + " must not be " + (isOsr ? "osr_" : "") + "compiled"); } - if (WHITE_BOX.getMethodCompilationLevel(method, isOsr) != 0) { - throw new RuntimeException(method + (isOsr ? " osr_" : " ") + + if (WHITE_BOX.getMethodCompilationLevel(executable, isOsr) != 0) { + throw new RuntimeException(executable + (isOsr ? " osr_" : " ") + "comp_level must be == 0"); } } @@ -242,21 +255,34 @@ public abstract class CompilerWhiteBoxTest { * has nonzero compilation level */ protected final void checkCompiled() { + checkCompiled(method, testCase.isOsr()); + } + + /** + * Checks, that the specified executable is compiled. + * + * @param executable The method or constructor to check. + * @param isOsr Check for OSR compilation if true + * @throws RuntimeException if {@linkplain #method} isn't in compiler queue + * and isn't compiled, or if {@linkplain #method} + * has nonzero compilation level + */ + protected static final void checkCompiled(Executable executable, boolean isOsr) { final long start = System.currentTimeMillis(); - waitBackgroundCompilation(); - if (WHITE_BOX.isMethodQueuedForCompilation(method)) { + waitBackgroundCompilation(executable); + if (WHITE_BOX.isMethodQueuedForCompilation(executable)) { System.err.printf("Warning: %s is still in queue after %dms%n", - method, System.currentTimeMillis() - start); + executable, System.currentTimeMillis() - start); return; } - if (!WHITE_BOX.isMethodCompiled(method, testCase.isOsr())) { - throw new RuntimeException(method + " must be " - + (testCase.isOsr() ? "osr_" : "") + "compiled"); + if (!WHITE_BOX.isMethodCompiled(executable, isOsr)) { + throw new RuntimeException(executable + " must be " + + (isOsr ? "osr_" : "") + "compiled"); } - if (WHITE_BOX.getMethodCompilationLevel(method, testCase.isOsr()) + if (WHITE_BOX.getMethodCompilationLevel(executable, isOsr) == 0) { - throw new RuntimeException(method - + (testCase.isOsr() ? " osr_" : " ") + throw new RuntimeException(executable + + (isOsr ? " osr_" : " ") + "comp_level must be != 0"); } } diff --git a/test/hotspot/jtreg/compiler/whitebox/DeoptimizeRelocatedNMethod.java b/test/hotspot/jtreg/compiler/whitebox/DeoptimizeRelocatedNMethod.java new file mode 100644 index 00000000000..25314051fdd --- /dev/null +++ b/test/hotspot/jtreg/compiler/whitebox/DeoptimizeRelocatedNMethod.java @@ -0,0 +1,157 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test id=Serial + * @bug 8316694 + * @library /test/lib / + * @modules java.base/jdk.internal.misc java.management + * @requires vm.opt.DeoptimizeALot != true + * @requires vm.gc.Serial + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbatch -XX:+SegmentedCodeCache -XX:+UseSerialGC + * -XX:+UnlockExperimentalVMOptions -XX:+NMethodRelocation compiler.whitebox.DeoptimizeRelocatedNMethod + */ + +/* + * @test id=Parallel + * @bug 8316694 + * @library /test/lib / + * @modules java.base/jdk.internal.misc java.management + * @requires vm.opt.DeoptimizeALot != true + * @requires vm.gc.Parallel + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbatch -XX:+SegmentedCodeCache -XX:+UseParallelGC + * -XX:+UnlockExperimentalVMOptions -XX:+NMethodRelocation compiler.whitebox.DeoptimizeRelocatedNMethod + */ + +/* + * @test id=G1 + * @bug 8316694 + * @library /test/lib / + * @modules java.base/jdk.internal.misc java.management + * @requires vm.opt.DeoptimizeALot != true + * @requires vm.gc.G1 + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbatch -XX:+SegmentedCodeCache -XX:+UseG1GC + * -XX:+UnlockExperimentalVMOptions -XX:+NMethodRelocation compiler.whitebox.DeoptimizeRelocatedNMethod + */ + +/* + * @test id=Shenandoah + * @bug 8316694 + * @library /test/lib / + * @modules java.base/jdk.internal.misc java.management + * @requires vm.opt.DeoptimizeALot != true + * @requires vm.gc.Shenandoah + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbatch -XX:+SegmentedCodeCache -XX:+UseShenandoahGC + * -XX:+UnlockExperimentalVMOptions -XX:+NMethodRelocation compiler.whitebox.DeoptimizeRelocatedNMethod + */ + +/* + * @test id=ZGC + * @bug 8316694 + * @library /test/lib / + * @modules java.base/jdk.internal.misc java.management + * @requires vm.opt.DeoptimizeALot != true + * @requires vm.gc.Z + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbatch -XX:+SegmentedCodeCache -XX:+UseZGC + * -XX:+UnlockExperimentalVMOptions -XX:+NMethodRelocation compiler.whitebox.DeoptimizeRelocatedNMethod + */ + +package compiler.whitebox; + +import compiler.whitebox.CompilerWhiteBoxTest; +import java.lang.reflect.Method; +import jdk.test.whitebox.WhiteBox; +import jdk.test.whitebox.code.BlobType; +import jdk.test.whitebox.code.NMethod; + +public class DeoptimizeRelocatedNMethod { + + private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); + public static double FUNCTION_RESULT = 0; + + public static void main(String [] args) throws Exception { + // Get method that will be relocated + Method method = DeoptimizeRelocatedNMethod.class.getMethod("function"); + WHITE_BOX.testSetDontInlineMethod(method, true); + + // Verify not initially compiled + CompilerWhiteBoxTest.checkNotCompiled(method, false); + + // Call function enough to compile + callFunction(); + + // Verify now compiled + CompilerWhiteBoxTest.checkCompiled(method, false); + + // Get newly created nmethod + NMethod origNmethod = NMethod.get(method, false); + + // Relocate nmethod and mark old for cleanup + WHITE_BOX.relocateNMethodFromMethod(method, BlobType.MethodProfiled.id); + + // Trigger GC to clean up old nmethod + WHITE_BOX.fullGC(); + + // Verify function still compiled after old was cleaned up + CompilerWhiteBoxTest.checkCompiled(method, false); + + // Get new nmethod and verify it's actually new + NMethod newNmethod = NMethod.get(method, false); + if (origNmethod.entry_point == newNmethod.entry_point) { + throw new RuntimeException("Did not create new nmethod"); + } + + // Call to verify everything still works + function(); + + // Deoptimized method + WHITE_BOX.deoptimizeMethod(method); + + CompilerWhiteBoxTest.checkNotCompiled(method, false); + + // Call to verify everything still works + function(); + } + + // Call function multiple times to trigger compilation + private static void callFunction() { + for (int i = 0; i < CompilerWhiteBoxTest.THRESHOLD; i++) { + function(); + } + } + + public static void function() { + FUNCTION_RESULT = Math.random(); + } +} diff --git a/test/hotspot/jtreg/compiler/whitebox/RelocateNMethod.java b/test/hotspot/jtreg/compiler/whitebox/RelocateNMethod.java new file mode 100644 index 00000000000..c18a8afa400 --- /dev/null +++ b/test/hotspot/jtreg/compiler/whitebox/RelocateNMethod.java @@ -0,0 +1,146 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test id=Serial + * @bug 8316694 + * @summary test that nmethod::relocate() correctly creates a new nmethod + * @library /test/lib / + * @modules java.base/jdk.internal.misc java.management + * + * @requires vm.opt.DeoptimizeALot != true + * @requires vm.gc.Serial + * + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbatch -XX:+SegmentedCodeCache + * -XX:+UseSerialGC -XX:+UnlockExperimentalVMOptions -XX:+NMethodRelocation compiler.whitebox.RelocateNMethod + */ + +/* + * @test id=Parallel + * @bug 8316694 + * @summary test that nmethod::relocate() correctly creates a new nmethod + * @library /test/lib / + * @modules java.base/jdk.internal.misc java.management + * + * @requires vm.opt.DeoptimizeALot != true + * @requires vm.gc.Parallel + * + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbatch -XX:+SegmentedCodeCache + * -XX:+UseParallelGC -XX:+UnlockExperimentalVMOptions -XX:+NMethodRelocation compiler.whitebox.RelocateNMethod + */ + +/* + * @test id=G1 + * @bug 8316694 + * @summary test that nmethod::relocate() correctly creates a new nmethod + * @library /test/lib / + * @modules java.base/jdk.internal.misc java.management + * + * @requires vm.opt.DeoptimizeALot != true + * @requires vm.gc.G1 + * + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbatch -XX:+SegmentedCodeCache + * -XX:+UseG1GC -XX:+UnlockExperimentalVMOptions -XX:+NMethodRelocation compiler.whitebox.RelocateNMethod + */ + +/* + * @test id=Shenandoah + * @bug 8316694 + * @summary test that nmethod::relocate() correctly creates a new nmethod + * @library /test/lib / + * @modules java.base/jdk.internal.misc java.management + * + * @requires vm.opt.DeoptimizeALot != true + * @requires vm.gc.Shenandoah + * + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbatch -XX:+SegmentedCodeCache + * -XX:+UseShenandoahGC -XX:+UnlockExperimentalVMOptions -XX:+NMethodRelocation compiler.whitebox.RelocateNMethod + */ + +/* + * @test id=ZGC + * @bug 8316694 + * @summary test that nmethod::relocate() correctly creates a new nmethod + * @library /test/lib / + * @modules java.base/jdk.internal.misc java.management + * + * @requires vm.opt.DeoptimizeALot != true + * @requires vm.gc.Z + * + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbatch -XX:+SegmentedCodeCache + * -XX:+UseZGC -XX:+UnlockExperimentalVMOptions -XX:+NMethodRelocation compiler.whitebox.RelocateNMethod + */ + +package compiler.whitebox; + +import java.lang.reflect.Method; +import jdk.test.whitebox.code.BlobType; +import jdk.test.whitebox.code.NMethod; +import jdk.test.whitebox.WhiteBox; + +import compiler.whitebox.CompilerWhiteBoxTest; + +public class RelocateNMethod extends CompilerWhiteBoxTest { + + public static void main(String[] args) throws Exception { + CompilerWhiteBoxTest.main(RelocateNMethod::new, new String[] {"CONSTRUCTOR_TEST", "METHOD_TEST", "STATIC_TEST"}); + } + + private RelocateNMethod(TestCase testCase) { + super(testCase); + // to prevent inlining of #method + WHITE_BOX.testSetDontInlineMethod(method, true); + } + + @Override + protected void test() throws Exception { + checkNotCompiled(); + + compile(); + + checkCompiled(); + NMethod origNmethod = NMethod.get(method, false); + + WHITE_BOX.relocateNMethodFromMethod(method, BlobType.MethodProfiled.id); + + WHITE_BOX.fullGC(); + + checkCompiled(); + + NMethod newNmethod = NMethod.get(method, false); + if (origNmethod.entry_point == newNmethod.entry_point) { + throw new RuntimeException("Did not create new nmethod"); + } + } +} diff --git a/test/hotspot/jtreg/compiler/whitebox/RelocateNMethodMultiplePaths.java b/test/hotspot/jtreg/compiler/whitebox/RelocateNMethodMultiplePaths.java new file mode 100644 index 00000000000..49be3eff8c2 --- /dev/null +++ b/test/hotspot/jtreg/compiler/whitebox/RelocateNMethodMultiplePaths.java @@ -0,0 +1,261 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test id=SerialC1 + * @bug 8316694 + * @requires vm.debug == true + * @requires vm.gc.Serial + * @summary test that relocated nmethod is correctly deoptimized + * @library /test/lib / + * @modules java.base/jdk.internal.misc java.management + * + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbatch -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:+SegmentedCodeCache -XX:-DeoptimizeRandom -XX:+DeoptimizeALot -XX:+UseSerialGC -XX:+UnlockExperimentalVMOptions -XX:+NMethodRelocation + * compiler.whitebox.RelocateNMethodMultiplePaths + */ + +/* + * @test id=SerialC2 + * @bug 8316694 + * @requires vm.debug == true + * @requires vm.gc.Serial + * @summary test that relocated nmethod is correctly deoptimized + * @library /test/lib / + * @modules java.base/jdk.internal.misc java.management + * + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbatch -XX:+TieredCompilation + * -XX:+SegmentedCodeCache -XX:-DeoptimizeRandom -XX:+DeoptimizeALot -XX:+UseSerialGC -XX:+UnlockExperimentalVMOptions -XX:+NMethodRelocation + * compiler.whitebox.RelocateNMethodMultiplePaths + */ + +/* + * @test id=ParallelC1 + * @bug 8316694 + * @requires vm.debug == true + * @requires vm.gc.Parallel + * @summary test that relocated nmethod is correctly deoptimized + * @library /test/lib / + * @modules java.base/jdk.internal.misc java.management + * + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbatch -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:+SegmentedCodeCache -XX:-DeoptimizeRandom -XX:+DeoptimizeALot -XX:+UseParallelGC -XX:+UnlockExperimentalVMOptions -XX:+NMethodRelocation + * compiler.whitebox.RelocateNMethodMultiplePaths + */ + +/* + * @test id=ParallelC2 + * @bug 8316694 + * @requires vm.debug == true + * @requires vm.gc.Parallel + * @summary test that relocated nmethod is correctly deoptimized + * @library /test/lib / + * @modules java.base/jdk.internal.misc java.management + * + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbatch -XX:+TieredCompilation + * -XX:+SegmentedCodeCache -XX:-DeoptimizeRandom -XX:+DeoptimizeALot -XX:+UseParallelGC -XX:+UnlockExperimentalVMOptions -XX:+NMethodRelocation + * compiler.whitebox.RelocateNMethodMultiplePaths + */ + +/* + * @test id=G1C1 + * @bug 8316694 + * @requires vm.debug == true + * @requires vm.gc.G1 + * @summary test that relocated nmethod is correctly deoptimized + * @library /test/lib / + * @modules java.base/jdk.internal.misc java.management + * + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbatch -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:+SegmentedCodeCache -XX:-DeoptimizeRandom -XX:+DeoptimizeALot -XX:+UseG1GC -XX:+UnlockExperimentalVMOptions -XX:+NMethodRelocation + * compiler.whitebox.RelocateNMethodMultiplePaths + */ + +/* + * @test id=G1C2 + * @bug 8316694 + * @requires vm.debug == true + * @requires vm.gc.G1 + * @summary test that relocated nmethod is correctly deoptimized + * @library /test/lib / + * @modules java.base/jdk.internal.misc java.management + * + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbatch -XX:+TieredCompilation + * -XX:+SegmentedCodeCache -XX:-DeoptimizeRandom -XX:+DeoptimizeALot -XX:+UseG1GC -XX:+UnlockExperimentalVMOptions -XX:+NMethodRelocation + * compiler.whitebox.RelocateNMethodMultiplePaths + */ + +/* + * @test id=ShenandoahC1 + * @bug 8316694 + * @requires vm.debug == true + * @requires vm.gc.Shenandoah + * @summary test that relocated nmethod is correctly deoptimized + * @library /test/lib / + * @modules java.base/jdk.internal.misc java.management + * + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbatch -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:+SegmentedCodeCache -XX:-DeoptimizeRandom -XX:+DeoptimizeALot -XX:+UseShenandoahGC -XX:+UnlockExperimentalVMOptions -XX:+NMethodRelocation + * compiler.whitebox.RelocateNMethodMultiplePaths + */ + +/* + * @test id=ShenandoahC2 + * @bug 8316694 + * @requires vm.debug == true + * @requires vm.gc.Shenandoah + * @summary test that relocated nmethod is correctly deoptimized + * @library /test/lib / + * @modules java.base/jdk.internal.misc java.management + * + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbatch -XX:+TieredCompilation + * -XX:+SegmentedCodeCache -XX:-DeoptimizeRandom -XX:+DeoptimizeALot -XX:+UseShenandoahGC -XX:+UnlockExperimentalVMOptions -XX:+NMethodRelocation + * compiler.whitebox.RelocateNMethodMultiplePaths + */ + +/* + * @test id=ZGCC1 + * @bug 8316694 + * @requires vm.debug == true + * @requires vm.gc.Z + * @summary test that relocated nmethod is correctly deoptimized + * @library /test/lib / + * @modules java.base/jdk.internal.misc java.management + * + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbatch -XX:+TieredCompilation -XX:TieredStopAtLevel=1 + * -XX:+SegmentedCodeCache -XX:-DeoptimizeRandom -XX:+DeoptimizeALot -XX:+UseZGC -XX:+UnlockExperimentalVMOptions -XX:+NMethodRelocation + * compiler.whitebox.RelocateNMethodMultiplePaths + */ + +/* + * @test id=ZGCC2 + * @bug 8316694 + * @requires vm.debug == true + * @requires vm.gc.Z + * @summary test that relocated nmethod is correctly deoptimized + * @library /test/lib / + * @modules java.base/jdk.internal.misc java.management + * + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbatch -XX:+TieredCompilation + * -XX:+SegmentedCodeCache -XX:-DeoptimizeRandom -XX:+DeoptimizeALot -XX:+UseZGC -XX:+UnlockExperimentalVMOptions -XX:+NMethodRelocation + * compiler.whitebox.RelocateNMethodMultiplePaths + */ + +package compiler.whitebox; + +import compiler.whitebox.CompilerWhiteBoxTest; +import java.lang.reflect.Method; +import jdk.test.whitebox.WhiteBox; +import jdk.test.whitebox.code.BlobType; +import jdk.test.whitebox.code.NMethod; + +public class RelocateNMethodMultiplePaths { + + private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); + + private static final int PATH_ONE_RESULT = 1; + private static final int PATH_TWO_RESULT = 2; + + public static void main(String [] args) throws Exception { + // Get method that will be relocated + Method method = RelocateNMethodMultiplePaths.class.getMethod("function", boolean.class); + WHITE_BOX.testSetDontInlineMethod(method, true); + + // Verify not initially compiled + CompilerWhiteBoxTest.checkNotCompiled(method, false); + + // Call function enough to compile + callFunction(true); + + // Verify now compiled + CompilerWhiteBoxTest.checkCompiled(method, false); + + // Get newly created nmethod + NMethod origNmethod = NMethod.get(method, false); + + // Relocate nmethod and mark old for cleanup + WHITE_BOX.relocateNMethodFromMethod(method, BlobType.MethodNonProfiled.id); + + // Trigger GC to clean up old nmethod + WHITE_BOX.fullGC(); + + // Verify function still compiled after old was cleaned up + CompilerWhiteBoxTest.checkCompiled(method, false); + + // Get new nmethod and verify it's actually new + NMethod newNmethod = NMethod.get(method, false); + if (origNmethod.entry_point == newNmethod.entry_point) { + throw new RuntimeException("Did not create new nmethod"); + } + + // Verify function still produces correct result + if (function(true) != PATH_ONE_RESULT) { + throw new RuntimeException("Relocated function produced incorrect result in path one"); + } + + // Call function again with different path and verify result + if (function(false) != PATH_TWO_RESULT) { + throw new RuntimeException("Relocated function produced incorrect result in path two"); + } + + // Verify function can be correctly deoptimized + WHITE_BOX.deoptimizeMethod(method); + CompilerWhiteBoxTest.checkNotCompiled(method, false); + } + + // Call function multiple times to trigger compilation + private static void callFunction(boolean pathOne) { + for (int i = 0; i < CompilerWhiteBoxTest.THRESHOLD; i++) { + function(pathOne); + } + } + + public static int function(boolean pathOne) { + if (pathOne) { + return PATH_ONE_RESULT; + } else { + return PATH_TWO_RESULT; + } + } +} diff --git a/test/hotspot/jtreg/compiler/whitebox/StressNMethodRelocation.java b/test/hotspot/jtreg/compiler/whitebox/StressNMethodRelocation.java new file mode 100644 index 00000000000..3b397f48306 --- /dev/null +++ b/test/hotspot/jtreg/compiler/whitebox/StressNMethodRelocation.java @@ -0,0 +1,239 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test StressNMethodRelocation + * @summary Call and relocate methods concurrently + * @library /test/lib / + * @modules java.base/jdk.internal.misc + * java.management + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * -XX:+SegmentedCodeCache -XX:+UnlockExperimentalVMOptions + * -XX:+NMethodRelocation compiler.whitebox.StressNMethodRelocation + */ + +package compiler.whitebox; + +import jdk.test.whitebox.WhiteBox; +import jdk.test.whitebox.code.BlobType; +import jdk.test.whitebox.code.CodeBlob; +import jdk.test.whitebox.code.NMethod; + +import jdk.test.lib.compiler.InMemoryJavaCompiler; + +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.EnumSet; +import java.util.Random; + +public class StressNMethodRelocation { + private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); + private static final int C2_LEVEL = 4; + private static final int ACTIVE_METHODS = 1024; + + private static TestMethod[] methods; + private static byte[] num1; + private static byte[] num2; + + private static long DURATION = 60_000; + + public static void main(String[] args) throws Exception { + // Initialize defaults + initNums(); + + // Generate compiled code + methods = new TestMethod[ACTIVE_METHODS]; + generateCode(methods); + + // Create thread that runs compiled methods + RunMethods runMethods = new RunMethods(); + Thread runMethodsThread = new Thread(runMethods); + + // Create thread that relocates compiled methods + RelocateNMethods relocate = new RelocateNMethods(); + Thread relocateThread = new Thread(relocate); + + // Start theads + runMethodsThread.start(); + relocateThread.start(); + + // Wait for threads to finish + runMethodsThread.join(); + relocateThread.join(); + } + + private static byte[] genNum(Random random, int digitCount) { + byte[] num = new byte[digitCount]; + int d; + do { + d = random.nextInt(10); + } while (d == 0); + + num[0] = (byte)d; + for (int i = 1; i < digitCount; ++i) { + num[i] = (byte)random.nextInt(10); + } + return num; + } + + private static void initNums() { + final long seed = 8374592837465123L; + Random random = new Random(seed); + + final int digitCount = 40; + num1 = genNum(random, digitCount); + num2 = genNum(random, digitCount); + } + + private static void generateCode(TestMethod[] m) throws Exception { + byte[] result = new byte[num1.length + 1]; + + for (int i = 0; i < ACTIVE_METHODS; ++i) { + m[i] = new TestMethod(); + m[i].profile(num1, num2, result); + m[i].compileWithC2(); + } + } + + private static final class TestMethod { + private static final String CLASS_NAME = "A"; + private static final String METHOD_TO_COMPILE = "sum"; + private static final String JAVA_CODE = """ + public class A { + + public static void sum(byte[] n1, byte[] n2, byte[] out) { + final int digitCount = n1.length; + int carry = 0; + for (int i = digitCount - 1; i >= 0; --i) { + int sum = n1[i] + n2[i] + carry; + out[i] = (byte)(sum % 10); + carry = sum / 10; + } + if (carry != 0) { + for (int i = digitCount; i > 0; --i) { + out[i] = out[i - 1]; + } + out[0] = (byte)carry; + } + } + }"""; + + private static final byte[] BYTE_CODE; + + static { + BYTE_CODE = InMemoryJavaCompiler.compile(CLASS_NAME, JAVA_CODE); + } + + private final Method method; + + private static ClassLoader createClassLoaderFor() { + return new ClassLoader() { + @Override + public Class loadClass(String name) throws ClassNotFoundException { + if (!name.equals(CLASS_NAME)) { + return super.loadClass(name); + } + + return defineClass(name, BYTE_CODE, 0, BYTE_CODE.length); + } + }; + } + + public TestMethod() throws Exception { + var cl = createClassLoaderFor().loadClass(CLASS_NAME); + method = cl.getMethod(METHOD_TO_COMPILE, byte[].class, byte[].class, byte[].class); + WHITE_BOX.testSetDontInlineMethod(method, true); + } + + public void profile(byte[] num1, byte[] num2, byte[] result) throws Exception { + method.invoke(null, num1, num2, result); + WHITE_BOX.markMethodProfiled(method); + } + + public void invoke(byte[] num1, byte[] num2, byte[] result) throws Exception { + method.invoke(null, num1, num2, result); + } + + public void compileWithC2() throws Exception { + WHITE_BOX.enqueueMethodForCompilation(method, C2_LEVEL); + while (WHITE_BOX.isMethodQueuedForCompilation(method)) { + Thread.onSpinWait(); + } + if (WHITE_BOX.getMethodCompilationLevel(method) != C2_LEVEL) { + throw new IllegalStateException("Method " + method + " is not compiled by C2."); + } + } + } + + private static final class RelocateNMethods implements Runnable { + public RelocateNMethods() {} + + // Move nmethod back and forth between NonProfiled and Profiled code heaps + public void run() { + long startTime = System.currentTimeMillis(); + while (System.currentTimeMillis() - startTime < DURATION) { + // Relocate NonProfiled to Profiled + CodeBlob[] nonProfiledBlobs = CodeBlob.getCodeBlobs(BlobType.MethodNonProfiled); + for (CodeBlob blob : nonProfiledBlobs) { + if (blob.isNMethod) { + WHITE_BOX.relocateNMethodFromAddr(blob.address, BlobType.MethodProfiled.id); + } + } + + // Relocate Profiled to NonProfiled + CodeBlob[] profiledBlobs = CodeBlob.getCodeBlobs(BlobType.MethodProfiled); + for (CodeBlob blob : nonProfiledBlobs) { + if (blob.isNMethod) { + WHITE_BOX.relocateNMethodFromAddr(blob.address, BlobType.MethodNonProfiled.id); + } + } + } + } + } + + private static final class RunMethods implements Runnable { + public RunMethods() {} + + public void run() { + try { + long startTime = System.currentTimeMillis(); + while (System.currentTimeMillis() - startTime < DURATION) { + callMethods(); + } + } catch (Exception e) { + throw new RuntimeException(e.getMessage()); + } + } + + private void callMethods() throws Exception { + for (var m : methods) { + byte[] result = new byte[num1.length + 1]; + m.invoke(num1, num2, result); + } + } + } + +} diff --git a/test/hotspot/jtreg/serviceability/jvmti/NMethodRelocation/NMethodRelocationTest.java b/test/hotspot/jtreg/serviceability/jvmti/NMethodRelocation/NMethodRelocationTest.java new file mode 100644 index 00000000000..b12e2c3455c --- /dev/null +++ b/test/hotspot/jtreg/serviceability/jvmti/NMethodRelocation/NMethodRelocationTest.java @@ -0,0 +1,178 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * + * @bug 8316694 + * @summary Verify that nmethod relocation posts the correct JVMTI events + * @requires vm.jvmti + * @library /test/lib /test/hotspot/jtreg + * @build jdk.test.whitebox.WhiteBox + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm/native NMethodRelocationTest + */ + +import static compiler.whitebox.CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION; + +import java.lang.reflect.Executable; +import java.util.Objects; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import jdk.test.lib.Asserts; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; +import jdk.test.whitebox.WhiteBox; +import jdk.test.whitebox.code.BlobType; +import jdk.test.whitebox.code.NMethod; + + +public class NMethodRelocationTest { + public static void main(String[] args) throws Exception { + ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder( + "-agentlib:NMethodRelocationTest", + "--enable-native-access=ALL-UNNAMED", + "-Xbootclasspath/a:.", + "-XX:+UseSerialGC", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:+WhiteBoxAPI", + "-XX:+SegmentedCodeCache", + "-XX:-TieredCompilation", + "-XX:+UnlockExperimentalVMOptions", + "-XX:+NMethodRelocation", + "DoWork"); + + OutputAnalyzer oa = new OutputAnalyzer(pb.start()); + String output = oa.getOutput(); + if (oa.getExitValue() != 0) { + System.err.println(oa.getOutput()); + throw new RuntimeException("Non-zero exit code returned from the test"); + } + Asserts.assertTrue(oa.getExitValue() == 0); + + Pattern pattern = Pattern.compile("(?m)^Relocated nmethod from (0x[0-9a-f]{16}) to (0x[0-9a-f]{16})$"); + Matcher matcher = pattern.matcher(output); + + if (matcher.find()) { + String fromAddr = matcher.group(1); + String toAddr = matcher.group(2); + + // Confirm events sent for both original and relocated nmethod + oa.shouldContain(": name: compiledMethod, code: " + fromAddr); + oa.shouldContain(": name: compiledMethod, code: " + toAddr); + oa.shouldContain(": name: compiledMethod, code: " + fromAddr); + oa.shouldContain(": name: compiledMethod, code: " + toAddr); + } else { + System.err.println(oa.getOutput()); + throw new RuntimeException("Unable to find relocation information"); + } + } +} + +class DoWork { + + protected static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); + + /** Load native library if required. */ + static { + try { + System.loadLibrary("NMethodRelocationTest"); + } catch (UnsatisfiedLinkError ule) { + System.err.println("Could not load NMethodRelocationTest library"); + System.err.println("java.library.path: " + + System.getProperty("java.library.path")); + throw ule; + } + } + + /** + * Returns value of VM option. + * + * @param name option's name + * @return value of option or {@code null}, if option doesn't exist + * @throws NullPointerException if name is null + */ + protected static String getVMOption(String name) { + Objects.requireNonNull(name); + return Objects.toString(WHITE_BOX.getVMFlag(name), null); + } + + /** + * Returns value of VM option or default value. + * + * @param name option's name + * @param defaultValue default value + * @return value of option or {@code defaultValue}, if option doesn't exist + * @throws NullPointerException if name is null + * @see #getVMOption(String) + */ + protected static String getVMOption(String name, String defaultValue) { + String result = getVMOption(name); + return result == null ? defaultValue : result; + } + + public static void main(String argv[]) throws Exception { + run(); + } + + public static void run() throws Exception { + Executable method = DoWork.class.getDeclaredMethod("compiledMethod"); + WHITE_BOX.testSetDontInlineMethod(method, true); + + WHITE_BOX.enqueueMethodForCompilation(method, COMP_LEVEL_FULL_OPTIMIZATION); + while (WHITE_BOX.isMethodQueuedForCompilation(method)) { + Thread.onSpinWait(); + } + + NMethod originalNMethod = NMethod.get(method, false); + if (originalNMethod == null) { + throw new AssertionError("Could not find original nmethod"); + } + + WHITE_BOX.relocateNMethodFromMethod(method, BlobType.MethodNonProfiled.id); + + NMethod relocatedNMethod = NMethod.get(method, false); + if (relocatedNMethod == null) { + throw new AssertionError("Could not find relocated nmethod"); + } + + if (originalNMethod.address == relocatedNMethod.address) { + throw new AssertionError("Relocated nmethod same as original"); + } + + WHITE_BOX.deoptimizeAll(); + + WHITE_BOX.fullGC(); + WHITE_BOX.fullGC(); + + WHITE_BOX.lockCompilation(); + + System.out.printf("Relocated nmethod from 0x%016x to 0x%016x%n", originalNMethod.code_begin, relocatedNMethod.code_begin); + System.out.flush(); + } + + public static long compiledMethod() { + return 0; + } +} diff --git a/test/hotspot/jtreg/serviceability/jvmti/NMethodRelocation/libNMethodRelocationTest.cpp b/test/hotspot/jtreg/serviceability/jvmti/NMethodRelocation/libNMethodRelocationTest.cpp new file mode 100644 index 00000000000..41ba6b10608 --- /dev/null +++ b/test/hotspot/jtreg/serviceability/jvmti/NMethodRelocation/libNMethodRelocationTest.cpp @@ -0,0 +1,114 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include +#include +#include +#include + +/** + * Callback for COMPILED_METHOD_LOAD event. + */ +JNIEXPORT void JNICALL +callbackCompiledMethodLoad(jvmtiEnv* jvmti, jmethodID method, + jint code_size, const void* code_addr, + jint map_length, const jvmtiAddrLocationMap* map, + const void* compile_info) { + char* name = nullptr; + char* sig = nullptr; + + if (jvmti->GetMethodName(method, &name, &sig, nullptr) != JVMTI_ERROR_NONE) { + printf(" [Could not retrieve method name]\n"); + fflush(stdout); + return; + } + + printf(": name: %s, code: 0x%016" PRIxPTR "\n", + name, (uintptr_t)code_addr); + fflush(stdout); +} + +/** + * Callback for COMPILED_METHOD_UNLOAD event. + */ +JNIEXPORT void JNICALL +callbackCompiledMethodUnload(jvmtiEnv* jvmti, jmethodID method, + const void* code_addr) { + char* name = nullptr; + char* sig = nullptr; + + if (jvmti->GetMethodName(method, &name, &sig, nullptr) != JVMTI_ERROR_NONE) { + printf(" [Could not retrieve method name]\n"); + fflush(stdout); + return; + } + printf(": name: %s, code: 0x%016" PRIxPTR "\n", + name, (uintptr_t)code_addr); + fflush(stdout); +} + +JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) { + jvmtiEnv* jvmti = nullptr; + jvmtiError error; + + if (jvm->GetEnv((void **)&jvmti, JVMTI_VERSION_1_0) != JNI_OK) { + printf("Unable to access JVMTI!\n"); + return JNI_ERR; + } + + // Add required capabilities + jvmtiCapabilities caps; + memset(&caps, 0, sizeof(caps)); + caps.can_generate_compiled_method_load_events = 1; + error = jvmti->AddCapabilities(&caps); + if (error != JVMTI_ERROR_NONE) { + printf("ERROR: Unable to add capabilities, error=%d\n", error); + return JNI_ERR; + } + + // Set event callbacks + jvmtiEventCallbacks eventCallbacks; + memset(&eventCallbacks, 0, sizeof(eventCallbacks)); + eventCallbacks.CompiledMethodLoad = callbackCompiledMethodLoad; + eventCallbacks.CompiledMethodUnload = callbackCompiledMethodUnload; + error = jvmti->SetEventCallbacks(&eventCallbacks, sizeof(eventCallbacks)); + if (error != JVMTI_ERROR_NONE) { + printf("ERROR: Unable to set event callbacks, error=%d\n", error); + return JNI_ERR; + } + + // Enable events + error = jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_COMPILED_METHOD_LOAD, nullptr); + if (error != JVMTI_ERROR_NONE) { + printf("ERROR: Unable to enable COMPILED_METHOD_LOAD event, error=%d\n", error); + return JNI_ERR; + } + + error = jvmti->SetEventNotificationMode(JVMTI_ENABLE, JVMTI_EVENT_COMPILED_METHOD_UNLOAD, nullptr); + if (error != JVMTI_ERROR_NONE) { + printf("ERROR: Unable to enable COMPILED_METHOD_UNLOAD event, error=%d\n", error); + return JNI_ERR; + } + + return JNI_OK; +} diff --git a/test/lib/jdk/test/whitebox/WhiteBox.java b/test/lib/jdk/test/whitebox/WhiteBox.java index 5adb7bf5127..669ec48b619 100644 --- a/test/lib/jdk/test/whitebox/WhiteBox.java +++ b/test/lib/jdk/test/whitebox/WhiteBox.java @@ -490,6 +490,12 @@ public class WhiteBox { Objects.requireNonNull(method); return getNMethod0(method, isOsr); } + private native void relocateNMethodFromMethod0(Executable method, int type); + public void relocateNMethodFromMethod(Executable method, int type) { + Objects.requireNonNull(method); + relocateNMethodFromMethod0(method, type); + } + public native void relocateNMethodFromAddr(long address, int type); public native long allocateCodeBlob(int size, int type); public long allocateCodeBlob(long size, int type) { int intSize = (int) size; diff --git a/test/lib/jdk/test/whitebox/code/CodeBlob.java b/test/lib/jdk/test/whitebox/code/CodeBlob.java index c6c23fdff0c..fd95b5a7e7d 100644 --- a/test/lib/jdk/test/whitebox/code/CodeBlob.java +++ b/test/lib/jdk/test/whitebox/code/CodeBlob.java @@ -46,18 +46,22 @@ public class CodeBlob { return new CodeBlob(obj); } protected CodeBlob(Object[] obj) { - assert obj.length == 4; + assert obj.length == 6; name = (String) obj[0]; size = (Integer) obj[1]; int blob_type_index = (Integer) obj[2]; code_blob_type = BlobType.values()[blob_type_index]; assert code_blob_type.id == (Integer) obj[2]; address = (Long) obj[3]; + code_begin = (Long) obj[4]; + isNMethod = (Boolean) obj[5]; } public final String name; public final int size; public final BlobType code_blob_type; public final long address; + public final long code_begin; + public final boolean isNMethod; @Override public String toString() { return "CodeBlob{" @@ -65,6 +69,7 @@ public class CodeBlob { + ", size=" + size + ", code_blob_type=" + code_blob_type + ", address=" + address + + ", code_begin=" + code_begin + '}'; } } From 5d9f94e05e1527745271d0167a418741607619e2 Mon Sep 17 00:00:00 2001 From: Vladimir Kozlov Date: Sun, 5 Oct 2025 16:20:53 +0000 Subject: [PATCH 0064/1639] 8369152: Problem list new tests from JDK-8316694 Reviewed-by: jpai, dholmes, serb --- test/hotspot/jtreg/ProblemList.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index d061236c957..f02ba70ba87 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -79,6 +79,17 @@ compiler/c2/TestVerifyConstraintCasts.java 8355574 generic-all compiler/c2/aarch64/TestStaticCallStub.java 8359963 linux-aarch64,macosx-aarch64 +compiler/whitebox/DeoptimizeRelocatedNMethod.java#G1 8369147 generic-all +compiler/whitebox/DeoptimizeRelocatedNMethod.java#Parallel 8369147 generic-all +compiler/whitebox/DeoptimizeRelocatedNMethod.java#Serial 8369147 generic-all +compiler/whitebox/DeoptimizeRelocatedNMethod.java#ZGC 8369147 generic-all +compiler/whitebox/RelocateNMethod.java#G1 8369147 generic-all +compiler/whitebox/RelocateNMethod.java#Parallel 8369147 generic-all +compiler/whitebox/RelocateNMethod.java#Serial 8369147 generic-all +compiler/whitebox/RelocateNMethod.java#ZGC 8369147 generic-all +compiler/whitebox/StressNMethodRelocation.java 8369147,8369148,8369149 generic-all +serviceability/jvmti/NMethodRelocation/NMethodRelocationTest.java 8369150,8369151 generic-all + ############################################################################# # :hotspot_gc From ba7bf43c76c94bea85dbbd865794184b7ee0cc86 Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Sun, 5 Oct 2025 23:55:53 +0000 Subject: [PATCH 0065/1639] 8365290: [perf] x86 ArrayFill intrinsic generates SPLIT_STORE for unaligned arrays Reviewed-by: sviswanathan, vpaprotski, kvn --- src/hotspot/cpu/x86/macroAssembler_x86.cpp | 47 ++++++++++++++++++---- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index c1319b2ef7f..77ee71c0382 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -5847,7 +5847,7 @@ void MacroAssembler::generate_fill(BasicType t, bool aligned, orl(value, rtmp); } - cmpptr(count, 2< Date: Mon, 6 Oct 2025 06:17:48 +0000 Subject: [PATCH 0066/1639] 8355354: C2 crashed: assert(_callee == nullptr || _callee == m) failed: repeated inline attempt with different callee Reviewed-by: vlivanov, dlong --- src/hotspot/share/opto/callGenerator.cpp | 4 ++ src/hotspot/share/opto/callGenerator.hpp | 1 + src/hotspot/share/opto/callnode.cpp | 52 +++++++++++++----------- src/hotspot/share/opto/compile.cpp | 6 +++ src/hotspot/share/opto/compile.hpp | 3 +- 5 files changed, 41 insertions(+), 25 deletions(-) diff --git a/src/hotspot/share/opto/callGenerator.cpp b/src/hotspot/share/opto/callGenerator.cpp index 03225044f5e..483cb731103 100644 --- a/src/hotspot/share/opto/callGenerator.cpp +++ b/src/hotspot/share/opto/callGenerator.cpp @@ -465,6 +465,10 @@ class LateInlineVirtualCallGenerator : public VirtualCallGenerator { // Convert the CallDynamicJava into an inline virtual void do_late_inline(); + virtual ciMethod* callee_method() { + return _callee; + } + virtual void set_callee_method(ciMethod* m) { assert(_callee == nullptr || _callee == m, "repeated inline attempt with different callee"); _callee = m; diff --git a/src/hotspot/share/opto/callGenerator.hpp b/src/hotspot/share/opto/callGenerator.hpp index 82b195e0c76..e24ea5e5356 100644 --- a/src/hotspot/share/opto/callGenerator.hpp +++ b/src/hotspot/share/opto/callGenerator.hpp @@ -88,6 +88,7 @@ class CallGenerator : public ArenaObj { virtual void set_unique_id(jlong id) { fatal("unique id only for late inlines"); }; virtual jlong unique_id() const { fatal("unique id only for late inlines"); return 0; }; + virtual ciMethod* callee_method() { ShouldNotReachHere(); } virtual void set_callee_method(ciMethod* callee) { ShouldNotReachHere(); } // Note: It is possible for a CG to be both inline and virtual. diff --git a/src/hotspot/share/opto/callnode.cpp b/src/hotspot/share/opto/callnode.cpp index 995208ba24f..ef1ebc5cef9 100644 --- a/src/hotspot/share/opto/callnode.cpp +++ b/src/hotspot/share/opto/callnode.cpp @@ -1228,33 +1228,37 @@ Node* CallDynamicJavaNode::Ideal(PhaseGVN* phase, bool can_reshape) { assert(IncrementalInlineVirtual, "required"); assert(cg->call_node() == this, "mismatch"); - // Recover symbolic info for method resolution. - ciMethod* caller = jvms()->method(); - ciBytecodeStream iter(caller); - iter.force_bci(jvms()->bci()); + if (cg->callee_method() == nullptr) { + // Recover symbolic info for method resolution. + ciMethod* caller = jvms()->method(); + ciBytecodeStream iter(caller); + iter.force_bci(jvms()->bci()); - bool not_used1; - ciSignature* not_used2; - ciMethod* orig_callee = iter.get_method(not_used1, ¬_used2); // callee in the bytecode - ciKlass* holder = iter.get_declared_method_holder(); - if (orig_callee->is_method_handle_intrinsic()) { - assert(_override_symbolic_info, "required"); - orig_callee = method(); - holder = method()->holder(); + bool not_used1; + ciSignature* not_used2; + ciMethod* orig_callee = iter.get_method(not_used1, ¬_used2); // callee in the bytecode + ciKlass* holder = iter.get_declared_method_holder(); + if (orig_callee->is_method_handle_intrinsic()) { + assert(_override_symbolic_info, "required"); + orig_callee = method(); + holder = method()->holder(); + } + + ciInstanceKlass* klass = ciEnv::get_instance_klass_for_declared_method_holder(holder); + + Node* receiver_node = in(TypeFunc::Parms); + const TypeOopPtr* receiver_type = phase->type(receiver_node)->isa_oopptr(); + + int not_used3; + bool call_does_dispatch; + ciMethod* callee = phase->C->optimize_virtual_call(caller, klass, holder, orig_callee, receiver_type, true /*is_virtual*/, + call_does_dispatch, not_used3); // out-parameters + if (!call_does_dispatch) { + cg->set_callee_method(callee); + } } - - ciInstanceKlass* klass = ciEnv::get_instance_klass_for_declared_method_holder(holder); - - Node* receiver_node = in(TypeFunc::Parms); - const TypeOopPtr* receiver_type = phase->type(receiver_node)->isa_oopptr(); - - int not_used3; - bool call_does_dispatch; - ciMethod* callee = phase->C->optimize_virtual_call(caller, klass, holder, orig_callee, receiver_type, true /*is_virtual*/, - call_does_dispatch, not_used3); // out-parameters - if (!call_does_dispatch) { + if (cg->callee_method() != nullptr) { // Register for late inlining. - cg->set_callee_method(callee); register_for_late_inline(); // MH late inlining prepends to the list, so do the same } } else { diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index 47de5acc2f2..7f63efe9e5e 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -2104,6 +2104,12 @@ bool Compile::inline_incrementally_one() { bool is_scheduled_for_igvn_before = C->igvn_worklist()->member(cg->call_node()); bool does_dispatch = cg->is_virtual_late_inline() || cg->is_mh_late_inline(); if (inlining_incrementally() || does_dispatch) { // a call can be either inlined or strength-reduced to a direct call + if (should_stress_inlining()) { + // randomly add repeated inline attempt if stress-inlining + cg->call_node()->set_generator(cg); + C->igvn_worklist()->push(cg->call_node()); + continue; + } cg->do_late_inline(); assert(_late_inlines.at(i) == cg, "no insertions before current position allowed"); if (failing()) { diff --git a/src/hotspot/share/opto/compile.hpp b/src/hotspot/share/opto/compile.hpp index 05c5f22dad9..a68da644d82 100644 --- a/src/hotspot/share/opto/compile.hpp +++ b/src/hotspot/share/opto/compile.hpp @@ -1094,7 +1094,8 @@ public: bool inline_incrementally_one(); void inline_incrementally_cleanup(PhaseIterGVN& igvn); void inline_incrementally(PhaseIterGVN& igvn); - bool should_delay_inlining() { return AlwaysIncrementalInline || (StressIncrementalInlining && (random() % 2) == 0); } + bool should_stress_inlining() { return StressIncrementalInlining && (random() % 2) == 0; } + bool should_delay_inlining() { return AlwaysIncrementalInline || should_stress_inlining(); } void inline_string_calls(bool parse_time); void inline_boxing_calls(PhaseIterGVN& igvn); bool optimize_loops(PhaseIterGVN& igvn, LoopOptsMode mode); From 069c569a710f50bc715f523c6c4c7aa087694af6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Sj=C3=B6len?= Date: Mon, 6 Oct 2025 07:48:45 +0000 Subject: [PATCH 0067/1639] 8368097: [asan] heap-buffer-overflow reported in ClassFileParser::skip_over_field_signature Reviewed-by: dholmes, mbaesken --- src/hotspot/share/classfile/classFileParser.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/classfile/classFileParser.cpp b/src/hotspot/share/classfile/classFileParser.cpp index fddd9df726b..87f2da91288 100644 --- a/src/hotspot/share/classfile/classFileParser.cpp +++ b/src/hotspot/share/classfile/classFileParser.cpp @@ -4678,11 +4678,15 @@ const char* ClassFileParser::skip_over_field_signature(const char* signature, return signature + 1; case JVM_SIGNATURE_CLASS: { if (_major_version < JAVA_1_5_VERSION) { + signature++; + length--; // Skip over the class name if one is there - const char* const p = skip_over_field_name(signature + 1, true, --length); - + const char* const p = skip_over_field_name(signature, true, length); + assert(p == nullptr || p > signature, "must parse one character at least"); // The next character better be a semicolon - if (p && (p - signature) > 1 && p[0] == JVM_SIGNATURE_ENDCLASS) { + if (p != nullptr && // Parse of field name succeeded. + p - signature < static_cast(length) && // There is at least one character left to parse. + p[0] == JVM_SIGNATURE_ENDCLASS) { return p + 1; } } From e6781fd9497723a7baab38d6bfb958ba1b1c24ff Mon Sep 17 00:00:00 2001 From: Fredrik Bredberg Date: Mon, 6 Oct 2025 08:10:11 +0000 Subject: [PATCH 0068/1639] 8367601: Remove held_monitor_count Reviewed-by: mdoerr, pchilanomate, fyang --- .../cpu/aarch64/globalDefinitions_aarch64.hpp | 2 - .../cpu/aarch64/macroAssembler_aarch64.cpp | 32 ---------- .../cpu/aarch64/macroAssembler_aarch64.hpp | 3 - .../cpu/aarch64/sharedRuntime_aarch64.cpp | 47 --------------- src/hotspot/cpu/ppc/globalDefinitions_ppc.hpp | 4 +- src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp | 58 +------------------ .../cpu/riscv/globalDefinitions_riscv.hpp | 4 +- .../cpu/riscv/macroAssembler_riscv.cpp | 30 ---------- .../cpu/riscv/macroAssembler_riscv.hpp | 5 +- src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp | 47 --------------- src/hotspot/cpu/x86/globalDefinitions_x86.hpp | 4 +- src/hotspot/cpu/x86/macroAssembler_x86.cpp | 8 --- src/hotspot/cpu/x86/macroAssembler_x86.hpp | 3 - src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp | 46 --------------- src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 1 - src/hotspot/share/runtime/continuation.hpp | 9 ++- .../share/runtime/continuationEntry.cpp | 1 - .../share/runtime/continuationEntry.hpp | 7 --- .../share/runtime/continuationFreezeThaw.cpp | 14 +---- src/hotspot/share/runtime/javaThread.cpp | 43 -------------- src/hotspot/share/runtime/javaThread.hpp | 12 ---- src/hotspot/share/runtime/objectMonitor.cpp | 1 - src/hotspot/share/runtime/sharedRuntime.cpp | 15 ----- src/hotspot/share/runtime/sharedRuntime.hpp | 3 - src/hotspot/share/runtime/synchronizer.cpp | 8 +-- .../share/runtime/synchronizer.inline.hpp | 2 - .../classes/jdk/internal/vm/Continuation.java | 9 +-- 27 files changed, 17 insertions(+), 401 deletions(-) diff --git a/src/hotspot/cpu/aarch64/globalDefinitions_aarch64.hpp b/src/hotspot/cpu/aarch64/globalDefinitions_aarch64.hpp index 948ba97aa22..1e788590b64 100644 --- a/src/hotspot/cpu/aarch64/globalDefinitions_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/globalDefinitions_aarch64.hpp @@ -35,8 +35,6 @@ const bool CCallingConventionRequiresIntsAsLongs = false; #define SUPPORTS_NATIVE_CX8 -#define SUPPORT_MONITOR_COUNT - // Aarch64 was not originally defined to be multi-copy-atomic, but now // is. See: "Simplifying ARM Concurrency: Multicopy-atomic Axiomatic // and Operational Models for ARMv8" diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index 3999beeec2b..2622bda1d0b 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -5630,38 +5630,6 @@ void MacroAssembler::tlab_allocate(Register obj, bs->tlab_allocate(this, obj, var_size_in_bytes, con_size_in_bytes, t1, t2, slow_case); } -void MacroAssembler::inc_held_monitor_count(Register tmp) { - Address dst(rthread, JavaThread::held_monitor_count_offset()); -#ifdef ASSERT - ldr(tmp, dst); - increment(tmp); - str(tmp, dst); - Label ok; - tbz(tmp, 63, ok); - STOP("assert(held monitor count underflow)"); - should_not_reach_here(); - bind(ok); -#else - increment(dst); -#endif -} - -void MacroAssembler::dec_held_monitor_count(Register tmp) { - Address dst(rthread, JavaThread::held_monitor_count_offset()); -#ifdef ASSERT - ldr(tmp, dst); - decrement(tmp); - str(tmp, dst); - Label ok; - tbz(tmp, 63, ok); - STOP("assert(held monitor count underflow)"); - should_not_reach_here(); - bind(ok); -#else - decrement(dst); -#endif -} - void MacroAssembler::verify_tlab() { #ifdef ASSERT if (UseTLAB && VerifyOops) { diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp index 0570fad5b8d..705bd19093c 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.hpp @@ -983,9 +983,6 @@ public: void push_cont_fastpath(Register java_thread = rthread); void pop_cont_fastpath(Register java_thread = rthread); - void inc_held_monitor_count(Register tmp); - void dec_held_monitor_count(Register tmp); - // Round up to a power of two void round_to(Register reg, int modulus); diff --git a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp index 70af8dd91d8..39609cbe0ac 100644 --- a/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/sharedRuntime_aarch64.cpp @@ -985,11 +985,8 @@ static void fill_continuation_entry(MacroAssembler* masm) { __ ldr(rscratch1, Address(rthread, JavaThread::cont_fastpath_offset())); __ str(rscratch1, Address(sp, ContinuationEntry::parent_cont_fastpath_offset())); - __ ldr(rscratch1, Address(rthread, JavaThread::held_monitor_count_offset())); - __ str(rscratch1, Address(sp, ContinuationEntry::parent_held_monitor_count_offset())); __ str(zr, Address(rthread, JavaThread::cont_fastpath_offset())); - __ str(zr, Address(rthread, JavaThread::held_monitor_count_offset())); } // on entry, sp points to the ContinuationEntry @@ -1005,50 +1002,6 @@ static void continuation_enter_cleanup(MacroAssembler* masm) { #endif __ ldr(rscratch1, Address(sp, ContinuationEntry::parent_cont_fastpath_offset())); __ str(rscratch1, Address(rthread, JavaThread::cont_fastpath_offset())); - - if (CheckJNICalls) { - // Check if this is a virtual thread continuation - Label L_skip_vthread_code; - __ ldrw(rscratch1, Address(sp, ContinuationEntry::flags_offset())); - __ cbzw(rscratch1, L_skip_vthread_code); - - // If the held monitor count is > 0 and this vthread is terminating then - // it failed to release a JNI monitor. So we issue the same log message - // that JavaThread::exit does. - __ ldr(rscratch1, Address(rthread, JavaThread::jni_monitor_count_offset())); - __ cbz(rscratch1, L_skip_vthread_code); - - // Save return value potentially containing the exception oop in callee-saved R19. - __ mov(r19, r0); - __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::log_jni_monitor_still_held)); - // Restore potential return value. - __ mov(r0, r19); - - // For vthreads we have to explicitly zero the JNI monitor count of the carrier - // on termination. The held count is implicitly zeroed below when we restore from - // the parent held count (which has to be zero). - __ str(zr, Address(rthread, JavaThread::jni_monitor_count_offset())); - - __ bind(L_skip_vthread_code); - } -#ifdef ASSERT - else { - // Check if this is a virtual thread continuation - Label L_skip_vthread_code; - __ ldrw(rscratch1, Address(sp, ContinuationEntry::flags_offset())); - __ cbzw(rscratch1, L_skip_vthread_code); - - // See comment just above. If not checking JNI calls the JNI count is only - // needed for assertion checking. - __ str(zr, Address(rthread, JavaThread::jni_monitor_count_offset())); - - __ bind(L_skip_vthread_code); - } -#endif - - __ ldr(rscratch1, Address(sp, ContinuationEntry::parent_held_monitor_count_offset())); - __ str(rscratch1, Address(rthread, JavaThread::held_monitor_count_offset())); - __ ldr(rscratch2, Address(sp, ContinuationEntry::parent_offset())); __ str(rscratch2, Address(rthread, JavaThread::cont_entry_offset())); __ add(rfp, sp, (int)ContinuationEntry::size()); diff --git a/src/hotspot/cpu/ppc/globalDefinitions_ppc.hpp b/src/hotspot/cpu/ppc/globalDefinitions_ppc.hpp index f8f15741301..6c41e56b20b 100644 --- a/src/hotspot/cpu/ppc/globalDefinitions_ppc.hpp +++ b/src/hotspot/cpu/ppc/globalDefinitions_ppc.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, 2016 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -43,8 +43,6 @@ const bool CCallingConventionRequiresIntsAsLongs = true; #define SUPPORTS_NATIVE_CX8 -#define SUPPORT_MONITOR_COUNT - // PPC64 is not specified as multi-copy-atomic // So we must not #define CPU_MULTI_COPY_ATOMIC diff --git a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp index aec36b3f3f9..9fe7e1f22ff 100644 --- a/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp +++ b/src/hotspot/cpu/ppc/sharedRuntime_ppc.cpp @@ -1639,7 +1639,6 @@ static void fill_continuation_entry(MacroAssembler* masm, Register reg_cont_obj, assert_different_registers(reg_cont_obj, reg_flags); Register zero = R8_ARG6; Register tmp2 = R9_ARG7; - Register tmp3 = R10_ARG8; DEBUG_ONLY(__ block_comment("fill {")); #ifdef ASSERT @@ -1655,12 +1654,9 @@ static void fill_continuation_entry(MacroAssembler* masm, Register reg_cont_obj, __ stw(zero, in_bytes(ContinuationEntry::pin_count_offset()), R1_SP); __ ld_ptr(tmp2, JavaThread::cont_fastpath_offset(), R16_thread); - __ ld(tmp3, in_bytes(JavaThread::held_monitor_count_offset()), R16_thread); __ st_ptr(tmp2, ContinuationEntry::parent_cont_fastpath_offset(), R1_SP); - __ std(tmp3, in_bytes(ContinuationEntry::parent_held_monitor_count_offset()), R1_SP); __ st_ptr(zero, JavaThread::cont_fastpath_offset(), R16_thread); - __ std(zero, in_bytes(JavaThread::held_monitor_count_offset()), R16_thread); DEBUG_ONLY(__ block_comment("} fill")); } @@ -1681,7 +1677,6 @@ static void fill_continuation_entry(MacroAssembler* masm, Register reg_cont_obj, static void continuation_enter_cleanup(MacroAssembler* masm) { Register tmp1 = R8_ARG6; Register tmp2 = R9_ARG7; - Register tmp3 = R10_ARG8; #ifdef ASSERT __ block_comment("clean {"); @@ -1692,57 +1687,8 @@ static void continuation_enter_cleanup(MacroAssembler* masm) { __ ld_ptr(tmp1, ContinuationEntry::parent_cont_fastpath_offset(), R1_SP); __ st_ptr(tmp1, JavaThread::cont_fastpath_offset(), R16_thread); - - if (CheckJNICalls) { - // Check if this is a virtual thread continuation - Label L_skip_vthread_code; - __ lwz(R0, in_bytes(ContinuationEntry::flags_offset()), R1_SP); - __ cmpwi(CR0, R0, 0); - __ beq(CR0, L_skip_vthread_code); - - // If the held monitor count is > 0 and this vthread is terminating then - // it failed to release a JNI monitor. So we issue the same log message - // that JavaThread::exit does. - __ ld(R0, in_bytes(JavaThread::jni_monitor_count_offset()), R16_thread); - __ cmpdi(CR0, R0, 0); - __ beq(CR0, L_skip_vthread_code); - - // Save return value potentially containing the exception oop - Register ex_oop = R15_esp; // nonvolatile register - __ mr(ex_oop, R3_RET); - __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::log_jni_monitor_still_held)); - // Restore potental return value - __ mr(R3_RET, ex_oop); - - // For vthreads we have to explicitly zero the JNI monitor count of the carrier - // on termination. The held count is implicitly zeroed below when we restore from - // the parent held count (which has to be zero). - __ li(tmp1, 0); - __ std(tmp1, in_bytes(JavaThread::jni_monitor_count_offset()), R16_thread); - - __ bind(L_skip_vthread_code); - } -#ifdef ASSERT - else { - // Check if this is a virtual thread continuation - Label L_skip_vthread_code; - __ lwz(R0, in_bytes(ContinuationEntry::flags_offset()), R1_SP); - __ cmpwi(CR0, R0, 0); - __ beq(CR0, L_skip_vthread_code); - - // See comment just above. If not checking JNI calls the JNI count is only - // needed for assertion checking. - __ li(tmp1, 0); - __ std(tmp1, in_bytes(JavaThread::jni_monitor_count_offset()), R16_thread); - - __ bind(L_skip_vthread_code); - } -#endif - - __ ld(tmp2, in_bytes(ContinuationEntry::parent_held_monitor_count_offset()), R1_SP); - __ ld_ptr(tmp3, ContinuationEntry::parent_offset(), R1_SP); - __ std(tmp2, in_bytes(JavaThread::held_monitor_count_offset()), R16_thread); - __ st_ptr(tmp3, JavaThread::cont_entry_offset(), R16_thread); + __ ld_ptr(tmp2, ContinuationEntry::parent_offset(), R1_SP); + __ st_ptr(tmp2, JavaThread::cont_entry_offset(), R16_thread); DEBUG_ONLY(__ block_comment("} clean")); } diff --git a/src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp b/src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp index 407017ee1c0..57223cf4390 100644 --- a/src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp +++ b/src/hotspot/cpu/riscv/globalDefinitions_riscv.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2015, Red Hat Inc. All rights reserved. * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -44,8 +44,6 @@ const bool CCallingConventionRequiresIntsAsLongs = false; #define SUPPORTS_NATIVE_CX8 -#define SUPPORT_MONITOR_COUNT - #define SUPPORT_RESERVED_STACK_AREA #define USE_POINTERS_TO_REGISTER_IMPL_ARRAY diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp index 5c85cc13bed..115b90a0087 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp @@ -225,36 +225,6 @@ void MacroAssembler::pop_cont_fastpath(Register java_thread) { bind(done); } -void MacroAssembler::inc_held_monitor_count(Register tmp) { - Address dst(xthread, JavaThread::held_monitor_count_offset()); - ld(tmp, dst); - addi(tmp, tmp, 1); - sd(tmp, dst); -#ifdef ASSERT - Label ok; - test_bit(tmp, tmp, 63); - beqz(tmp, ok); - STOP("assert(held monitor count overflow)"); - should_not_reach_here(); - bind(ok); -#endif -} - -void MacroAssembler::dec_held_monitor_count(Register tmp) { - Address dst(xthread, JavaThread::held_monitor_count_offset()); - ld(tmp, dst); - subi(tmp, tmp, 1); - sd(tmp, dst); -#ifdef ASSERT - Label ok; - test_bit(tmp, tmp, 63); - beqz(tmp, ok); - STOP("assert(held monitor count underflow)"); - should_not_reach_here(); - bind(ok); -#endif -} - int MacroAssembler::align(int modulus, int extra_offset) { CompressibleScope scope(this); intptr_t before = offset(); diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp index 13b70d5dbd7..9e713e90270 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved. * Copyright (c) 2020, 2024, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. @@ -849,9 +849,6 @@ public: void push_cont_fastpath(Register java_thread = xthread); void pop_cont_fastpath(Register java_thread = xthread); - void inc_held_monitor_count(Register tmp); - void dec_held_monitor_count(Register tmp); - // if heap base register is used - reinit it with the correct value void reinit_heapbase(); diff --git a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp index 94506e9f19d..b303178a666 100644 --- a/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp +++ b/src/hotspot/cpu/riscv/sharedRuntime_riscv.cpp @@ -885,11 +885,8 @@ static void fill_continuation_entry(MacroAssembler* masm) { __ ld(t0, Address(xthread, JavaThread::cont_fastpath_offset())); __ sd(t0, Address(sp, ContinuationEntry::parent_cont_fastpath_offset())); - __ ld(t0, Address(xthread, JavaThread::held_monitor_count_offset())); - __ sd(t0, Address(sp, ContinuationEntry::parent_held_monitor_count_offset())); __ sd(zr, Address(xthread, JavaThread::cont_fastpath_offset())); - __ sd(zr, Address(xthread, JavaThread::held_monitor_count_offset())); } // on entry, sp points to the ContinuationEntry @@ -905,50 +902,6 @@ static void continuation_enter_cleanup(MacroAssembler* masm) { __ ld(t0, Address(sp, ContinuationEntry::parent_cont_fastpath_offset())); __ sd(t0, Address(xthread, JavaThread::cont_fastpath_offset())); - - if (CheckJNICalls) { - // Check if this is a virtual thread continuation - Label L_skip_vthread_code; - __ lwu(t0, Address(sp, ContinuationEntry::flags_offset())); - __ beqz(t0, L_skip_vthread_code); - - // If the held monitor count is > 0 and this vthread is terminating then - // it failed to release a JNI monitor. So we issue the same log message - // that JavaThread::exit does. - __ ld(t0, Address(xthread, JavaThread::jni_monitor_count_offset())); - __ beqz(t0, L_skip_vthread_code); - - // Save return value potentially containing the exception oop in callee-saved x9 - __ mv(x9, x10); - __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::log_jni_monitor_still_held)); - // Restore potential return value - __ mv(x10, x9); - - // For vthreads we have to explicitly zero the JNI monitor count of the carrier - // on termination. The held count is implicitly zeroed below when we restore from - // the parent held count (which has to be zero). - __ sd(zr, Address(xthread, JavaThread::jni_monitor_count_offset())); - - __ bind(L_skip_vthread_code); - } -#ifdef ASSERT - else { - // Check if this is a virtual thread continuation - Label L_skip_vthread_code; - __ lwu(t0, Address(sp, ContinuationEntry::flags_offset())); - __ beqz(t0, L_skip_vthread_code); - - // See comment just above. If not checking JNI calls the JNI count is only - // needed for assertion checking. - __ sd(zr, Address(xthread, JavaThread::jni_monitor_count_offset())); - - __ bind(L_skip_vthread_code); - } -#endif - - __ ld(t0, Address(sp, ContinuationEntry::parent_held_monitor_count_offset())); - __ sd(t0, Address(xthread, JavaThread::held_monitor_count_offset())); - __ ld(t0, Address(sp, ContinuationEntry::parent_offset())); __ sd(t0, Address(xthread, JavaThread::cont_entry_offset())); __ add(fp, sp, (int)ContinuationEntry::size() + 2 * wordSize /* 2 extra words to match up with leave() */); diff --git a/src/hotspot/cpu/x86/globalDefinitions_x86.hpp b/src/hotspot/cpu/x86/globalDefinitions_x86.hpp index 3c1474ae861..abbeb66a1ca 100644 --- a/src/hotspot/cpu/x86/globalDefinitions_x86.hpp +++ b/src/hotspot/cpu/x86/globalDefinitions_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,8 +34,6 @@ const bool CCallingConventionRequiresIntsAsLongs = false; #define SUPPORTS_NATIVE_CX8 -#define SUPPORT_MONITOR_COUNT - #define CPU_MULTI_COPY_ATOMIC // The expected size in bytes of a cache line. diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index 77ee71c0382..4f19b30b832 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -2431,14 +2431,6 @@ void MacroAssembler::pop_cont_fastpath() { bind(L_done); } -void MacroAssembler::inc_held_monitor_count() { - incrementq(Address(r15_thread, JavaThread::held_monitor_count_offset())); -} - -void MacroAssembler::dec_held_monitor_count() { - decrementq(Address(r15_thread, JavaThread::held_monitor_count_offset())); -} - #ifdef ASSERT void MacroAssembler::stop_if_in_cont(Register cont, const char* name) { Label no_cont; diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.hpp b/src/hotspot/cpu/x86/macroAssembler_x86.hpp index 1c0dbaaefbe..ed1343d9c8c 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp @@ -472,9 +472,6 @@ class MacroAssembler: public Assembler { void push_cont_fastpath(); void pop_cont_fastpath(); - void inc_held_monitor_count(); - void dec_held_monitor_count(); - DEBUG_ONLY(void stop_if_in_cont(Register cont_reg, const char* name);) // Round up to a power of two diff --git a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp index e2a8f36b050..e702b587edd 100644 --- a/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp +++ b/src/hotspot/cpu/x86/sharedRuntime_x86_64.cpp @@ -1352,11 +1352,8 @@ static void fill_continuation_entry(MacroAssembler* masm, Register reg_cont_obj, __ movptr(rax, Address(r15_thread, JavaThread::cont_fastpath_offset())); __ movptr(Address(rsp, ContinuationEntry::parent_cont_fastpath_offset()), rax); - __ movq(rax, Address(r15_thread, JavaThread::held_monitor_count_offset())); - __ movq(Address(rsp, ContinuationEntry::parent_held_monitor_count_offset()), rax); __ movptr(Address(r15_thread, JavaThread::cont_fastpath_offset()), 0); - __ movq(Address(r15_thread, JavaThread::held_monitor_count_offset()), 0); } //---------------------------- continuation_enter_cleanup --------------------------- @@ -1380,49 +1377,6 @@ static void continuation_enter_cleanup(MacroAssembler* masm) { #endif __ movptr(rbx, Address(rsp, ContinuationEntry::parent_cont_fastpath_offset())); __ movptr(Address(r15_thread, JavaThread::cont_fastpath_offset()), rbx); - - if (CheckJNICalls) { - // Check if this is a virtual thread continuation - Label L_skip_vthread_code; - __ cmpl(Address(rsp, ContinuationEntry::flags_offset()), 0); - __ jcc(Assembler::equal, L_skip_vthread_code); - - // If the held monitor count is > 0 and this vthread is terminating then - // it failed to release a JNI monitor. So we issue the same log message - // that JavaThread::exit does. - __ cmpptr(Address(r15_thread, JavaThread::jni_monitor_count_offset()), 0); - __ jcc(Assembler::equal, L_skip_vthread_code); - - // rax may hold an exception oop, save it before the call - __ push(rax); - __ call_VM_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::log_jni_monitor_still_held)); - __ pop(rax); - - // For vthreads we have to explicitly zero the JNI monitor count of the carrier - // on termination. The held count is implicitly zeroed below when we restore from - // the parent held count (which has to be zero). - __ movq(Address(r15_thread, JavaThread::jni_monitor_count_offset()), 0); - - __ bind(L_skip_vthread_code); - } -#ifdef ASSERT - else { - // Check if this is a virtual thread continuation - Label L_skip_vthread_code; - __ cmpl(Address(rsp, ContinuationEntry::flags_offset()), 0); - __ jcc(Assembler::equal, L_skip_vthread_code); - - // See comment just above. If not checking JNI calls the JNI count is only - // needed for assertion checking. - __ movq(Address(r15_thread, JavaThread::jni_monitor_count_offset()), 0); - - __ bind(L_skip_vthread_code); - } -#endif - - __ movq(rbx, Address(rsp, ContinuationEntry::parent_held_monitor_count_offset())); - __ movq(Address(r15_thread, JavaThread::held_monitor_count_offset()), rbx); - __ movptr(rbx, Address(rsp, ContinuationEntry::parent_offset())); __ movptr(Address(r15_thread, JavaThread::cont_entry_offset()), rbx); __ addptr(rsp, checked_cast(ContinuationEntry::size())); diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index b4f033a4f9a..7ef16f6e32c 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -255,7 +255,6 @@ nonstatic_field(JavaThread, _should_post_on_exceptions_flag, int) \ nonstatic_field(JavaThread, _jni_environment, JNIEnv) \ nonstatic_field(JavaThread, _stack_overflow_state._reserved_stack_activation, address) \ - nonstatic_field(JavaThread, _held_monitor_count, intx) \ nonstatic_field(JavaThread, _lock_stack, LockStack) \ nonstatic_field(JavaThread, _om_cache, OMCache) \ nonstatic_field(JavaThread, _cont_entry, ContinuationEntry*) \ diff --git a/src/hotspot/share/runtime/continuation.hpp b/src/hotspot/share/runtime/continuation.hpp index e678e0bd42b..0cfd484361d 100644 --- a/src/hotspot/share/runtime/continuation.hpp +++ b/src/hotspot/share/runtime/continuation.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,10 +53,9 @@ enum freeze_result { freeze_ok_bottom = 1, freeze_pinned_cs = 2, freeze_pinned_native = 3, - freeze_pinned_monitor = 4, - freeze_exception = 5, - freeze_not_mounted = 6, - freeze_unsupported = 7 + freeze_exception = 4, + freeze_not_mounted = 5, + freeze_unsupported = 6 }; class Continuation : AllStatic { diff --git a/src/hotspot/share/runtime/continuationEntry.cpp b/src/hotspot/share/runtime/continuationEntry.cpp index 4551bfa7cc8..69a20808798 100644 --- a/src/hotspot/share/runtime/continuationEntry.cpp +++ b/src/hotspot/share/runtime/continuationEntry.cpp @@ -107,7 +107,6 @@ void ContinuationEntry::describe(FrameValues& values, int frame_no) const { values.describe(frame_no, (intptr_t*)(usp + in_bytes(ContinuationEntry::argsize_offset())), "argsize"); values.describe(frame_no, (intptr_t*)(usp + in_bytes(ContinuationEntry::pin_count_offset())), "pin_count"); values.describe(frame_no, (intptr_t*)(usp + in_bytes(ContinuationEntry::parent_cont_fastpath_offset())), "parent fastpath"); - values.describe(frame_no, (intptr_t*)(usp + in_bytes(ContinuationEntry::parent_held_monitor_count_offset())), "parent held monitor count"); } #endif diff --git a/src/hotspot/share/runtime/continuationEntry.hpp b/src/hotspot/share/runtime/continuationEntry.hpp index 3c8532b9e87..8361f2f912b 100644 --- a/src/hotspot/share/runtime/continuationEntry.hpp +++ b/src/hotspot/share/runtime/continuationEntry.hpp @@ -79,11 +79,6 @@ class ContinuationEntry { // The caller (if there is one) is the still frozen top frame in the StackChunk. int _argsize; intptr_t* _parent_cont_fastpath; -#ifdef _LP64 - int64_t _parent_held_monitor_count; -#else - int32_t _parent_held_monitor_count; -#endif uint32_t _pin_count; public: @@ -94,7 +89,6 @@ class ContinuationEntry { static ByteSize argsize_offset() { return byte_offset_of(ContinuationEntry, _argsize); } static ByteSize pin_count_offset(){ return byte_offset_of(ContinuationEntry, _pin_count); } static ByteSize parent_cont_fastpath_offset() { return byte_offset_of(ContinuationEntry, _parent_cont_fastpath); } - static ByteSize parent_held_monitor_count_offset() { return byte_offset_of(ContinuationEntry, _parent_held_monitor_count); } static address return_pc() { return _return_pc; } static address return_pc_address() { return (address)&_return_pc; } @@ -103,7 +97,6 @@ class ContinuationEntry { static size_t size() { return align_up((int)sizeof(ContinuationEntry), 2*wordSize); } ContinuationEntry* parent() const { return _parent; } - int64_t parent_held_monitor_count() const { return (int64_t)_parent_held_monitor_count; } static address entry_pc() { return _return_pc; } intptr_t* entry_sp() const { return (intptr_t*)this; } diff --git a/src/hotspot/share/runtime/continuationFreezeThaw.cpp b/src/hotspot/share/runtime/continuationFreezeThaw.cpp index 024b69c765f..33b4f2bf488 100644 --- a/src/hotspot/share/runtime/continuationFreezeThaw.cpp +++ b/src/hotspot/share/runtime/continuationFreezeThaw.cpp @@ -1736,13 +1736,10 @@ static inline freeze_result freeze_internal(JavaThread* current, intptr_t* const assert(entry->is_virtual_thread() == (entry->scope(current) == java_lang_VirtualThread::vthread_scope()), ""); - assert((current->held_monitor_count() == 0 && current->jni_monitor_count() == 0), - "Held monitor count should not be used for lightweight locking: " INT64_FORMAT " JNI: " INT64_FORMAT, (int64_t)current->held_monitor_count(), (int64_t)current->jni_monitor_count()); - - if (entry->is_pinned() || current->held_monitor_count() > 0) { - log_develop_debug(continuations)("PINNED due to critical section/hold monitor"); + if (entry->is_pinned()) { + log_develop_debug(continuations)("PINNED due to critical section"); verify_continuation(cont.continuation()); - freeze_result res = entry->is_pinned() ? freeze_pinned_cs : freeze_pinned_monitor; + const freeze_result res = freeze_pinned_cs; if (!preempt) { JFR_ONLY(current->set_last_freeze_fail_result(res);) } @@ -1799,8 +1796,6 @@ static freeze_result is_pinned0(JavaThread* thread, oop cont_scope, bool safepoi } if (entry->is_pinned()) { return freeze_pinned_cs; - } else if (thread->held_monitor_count() > 0) { - return freeze_pinned_monitor; } RegisterMap map(thread, @@ -1836,15 +1831,12 @@ static freeze_result is_pinned0(JavaThread* thread, oop cont_scope, bool safepoi if (scope == cont_scope) { break; } - intx monitor_count = entry->parent_held_monitor_count(); entry = entry->parent(); if (entry == nullptr) { break; } if (entry->is_pinned()) { return freeze_pinned_cs; - } else if (monitor_count > 0) { - return freeze_pinned_monitor; } } } diff --git a/src/hotspot/share/runtime/javaThread.cpp b/src/hotspot/share/runtime/javaThread.cpp index e5af8d7bedd..8bb8095878f 100644 --- a/src/hotspot/share/runtime/javaThread.cpp +++ b/src/hotspot/share/runtime/javaThread.cpp @@ -488,8 +488,6 @@ JavaThread::JavaThread(MemTag mem_tag) : _cont_entry(nullptr), _cont_fastpath(nullptr), _cont_fastpath_thread_state(1), - _held_monitor_count(0), - _jni_monitor_count(0), _unlocked_inflated_monitor(nullptr), _preempt_alternate_return(nullptr), @@ -927,27 +925,6 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) { "should not have a Java frame when detaching or exiting"); ObjectSynchronizer::release_monitors_owned_by_thread(this); assert(!this->has_pending_exception(), "release_monitors should have cleared"); - // Check for monitor counts being out of sync. - assert(held_monitor_count() == jni_monitor_count(), - "held monitor count should be equal to jni: %zd != %zd", - held_monitor_count(), jni_monitor_count()); - // All in-use monitors, including JNI-locked ones, should have been released above. - assert(held_monitor_count() == 0, "Failed to unlock %zd object monitors", - held_monitor_count()); - } else { - // Check for monitor counts being out of sync. - assert(held_monitor_count() == jni_monitor_count(), - "held monitor count should be equal to jni: %zd != %zd", - held_monitor_count(), jni_monitor_count()); - // It is possible that a terminating thread failed to unlock monitors it locked - // via JNI so we don't assert the count is zero. - } - - if (CheckJNICalls && jni_monitor_count() > 0) { - // We would like a fatal here, but due to we never checked this before there - // is a lot of tests which breaks, even with an error log. - log_debug(jni)("JavaThread %s (tid: %zu) with Objects still locked by JNI MonitorEnter.", - exit_type == JavaThread::normal_exit ? "exiting" : "detaching", os::current_thread_id()); } // These things needs to be done while we are still a Java Thread. Make sure that thread @@ -1988,26 +1965,6 @@ void JavaThread::trace_stack() { #endif // PRODUCT -// Slow-path increment of the held monitor counts. JNI locking is always -// this slow-path. -void JavaThread::inc_held_monitor_count(intx i, bool jni) { -#ifdef SUPPORT_MONITOR_COUNT - // Nothing to do. Just do some sanity check. - assert(_held_monitor_count == 0, "counter should not be used"); - assert(_jni_monitor_count == 0, "counter should not be used"); -#endif // SUPPORT_MONITOR_COUNT -} - -// Slow-path decrement of the held monitor counts. JNI unlocking is always -// this slow-path. -void JavaThread::dec_held_monitor_count(intx i, bool jni) { -#ifdef SUPPORT_MONITOR_COUNT - // Nothing to do. Just do some sanity check. - assert(_held_monitor_count == 0, "counter should not be used"); - assert(_jni_monitor_count == 0, "counter should not be used"); -#endif // SUPPORT_MONITOR_COUNT -} - frame JavaThread::vthread_last_frame() { assert (is_vthread_mounted(), "Virtual thread not mounted"); return last_frame(); diff --git a/src/hotspot/share/runtime/javaThread.hpp b/src/hotspot/share/runtime/javaThread.hpp index 89c3191669a..c8be1594a69 100644 --- a/src/hotspot/share/runtime/javaThread.hpp +++ b/src/hotspot/share/runtime/javaThread.hpp @@ -476,9 +476,6 @@ class JavaThread: public Thread { // frame inside the continuation that we know about int _cont_fastpath_thread_state; // whether global thread state allows continuation fastpath (JVMTI) - // It's signed for error detection. - intx _held_monitor_count; // used by continuations for fast lock detection - intx _jni_monitor_count; ObjectMonitor* _unlocked_inflated_monitor; // This is the field we poke in the interpreter and native @@ -662,13 +659,6 @@ private: bool cont_fastpath() const { return _cont_fastpath == nullptr && _cont_fastpath_thread_state != 0; } bool cont_fastpath_thread_state() const { return _cont_fastpath_thread_state != 0; } - void inc_held_monitor_count(intx i = 1, bool jni = false); - void dec_held_monitor_count(intx i = 1, bool jni = false); - - intx held_monitor_count() { return _held_monitor_count; } - intx jni_monitor_count() { return _jni_monitor_count; } - void clear_jni_monitor_count() { _jni_monitor_count = 0; } - // Support for SharedRuntime::monitor_exit_helper() ObjectMonitor* unlocked_inflated_monitor() const { return _unlocked_inflated_monitor; } void clear_unlocked_inflated_monitor() { @@ -897,8 +887,6 @@ public: static ByteSize cont_entry_offset() { return byte_offset_of(JavaThread, _cont_entry); } static ByteSize cont_fastpath_offset() { return byte_offset_of(JavaThread, _cont_fastpath); } - static ByteSize held_monitor_count_offset() { return byte_offset_of(JavaThread, _held_monitor_count); } - static ByteSize jni_monitor_count_offset() { return byte_offset_of(JavaThread, _jni_monitor_count); } static ByteSize preemption_cancelled_offset() { return byte_offset_of(JavaThread, _preemption_cancelled); } static ByteSize preempt_alternate_return_offset() { return byte_offset_of(JavaThread, _preempt_alternate_return); } static ByteSize unlocked_inflated_monitor_offset() { return byte_offset_of(JavaThread, _unlocked_inflated_monitor); } diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp index 8859f6e7f5f..4c00ecac697 100644 --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -1952,7 +1952,6 @@ void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) { int relock_count = JvmtiDeferredUpdates::get_and_reset_relock_count_after_wait(current); _recursions = save // restore the old recursion count + relock_count; // increased by the deferred relock count - current->inc_held_monitor_count(relock_count); // Deopt never entered these counts. _waiters--; // decrement the number of waiters // Verify a few postconditions diff --git a/src/hotspot/share/runtime/sharedRuntime.cpp b/src/hotspot/share/runtime/sharedRuntime.cpp index cf949fe1e7c..85aeba361ff 100644 --- a/src/hotspot/share/runtime/sharedRuntime.cpp +++ b/src/hotspot/share/runtime/sharedRuntime.cpp @@ -1980,7 +1980,6 @@ void SharedRuntime::monitor_exit_helper(oopDesc* obj, BasicLock* lock, JavaThrea if (!m->try_enter(current, /*check_for_recursion*/ false)) { // Some other thread acquired the lock (or the monitor was // deflated). Either way we are done. - current->dec_held_monitor_count(); return; } } @@ -2002,20 +2001,6 @@ JRT_LEAF(void, SharedRuntime::complete_monitor_unlocking_C(oopDesc* obj, BasicLo SharedRuntime::monitor_exit_helper(obj, lock, current); JRT_END -// This is only called when CheckJNICalls is true, and only -// for virtual thread termination. -JRT_LEAF(void, SharedRuntime::log_jni_monitor_still_held()) - assert(CheckJNICalls, "Only call this when checking JNI usage"); - if (log_is_enabled(Debug, jni)) { - JavaThread* current = JavaThread::current(); - int64_t vthread_id = java_lang_Thread::thread_id(current->vthread()); - int64_t carrier_id = java_lang_Thread::thread_id(current->threadObj()); - log_debug(jni)("VirtualThread (tid: " INT64_FORMAT ", carrier id: " INT64_FORMAT - ") exiting with Objects still locked by JNI MonitorEnter.", - vthread_id, carrier_id); - } -JRT_END - #ifndef PRODUCT void SharedRuntime::print_statistics() { diff --git a/src/hotspot/share/runtime/sharedRuntime.hpp b/src/hotspot/share/runtime/sharedRuntime.hpp index 6544e380d99..2a19b80c3b5 100644 --- a/src/hotspot/share/runtime/sharedRuntime.hpp +++ b/src/hotspot/share/runtime/sharedRuntime.hpp @@ -404,9 +404,6 @@ class SharedRuntime: AllStatic { static void monitor_exit_helper(oopDesc* obj, BasicLock* lock, JavaThread* current); - // Issue UL warning for unlocked JNI monitor on virtual thread termination - static void log_jni_monitor_still_held(); - private: static Handle find_callee_info(Bytecodes::Code& bc, CallInfo& callinfo, TRAPS); static Handle find_callee_info_helper(vframeStream& vfst, Bytecodes::Code& bc, CallInfo& callinfo, TRAPS); diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp index ff4e09e741f..e513c57fe06 100644 --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.cpp @@ -452,7 +452,6 @@ void ObjectSynchronizer::jni_enter(Handle obj, JavaThread* current) { while (true) { BasicLock lock; if (LightweightSynchronizer::inflate_and_enter(obj(), &lock, inflate_cause_jni_enter, current, current) != nullptr) { - current->inc_held_monitor_count(1, true); break; } } @@ -470,7 +469,6 @@ void ObjectSynchronizer::jni_exit(oop obj, TRAPS) { // monitor even if an exception was already pending. if (monitor->check_owner(THREAD)) { monitor->exit(current); - current->dec_held_monitor_count(1, true); } } @@ -1263,8 +1261,7 @@ class ReleaseJavaMonitorsClosure: public MonitorClosure { public: ReleaseJavaMonitorsClosure(JavaThread* thread) : _thread(thread) {} void do_monitor(ObjectMonitor* mid) { - intx rec = mid->complete_exit(_thread); - _thread->dec_held_monitor_count(rec + 1); + mid->complete_exit(_thread); } }; @@ -1290,9 +1287,6 @@ void ObjectSynchronizer::release_monitors_owned_by_thread(JavaThread* current) { ObjectSynchronizer::owned_monitors_iterate(&rjmc, current); assert(!current->has_pending_exception(), "Should not be possible"); current->clear_pending_exception(); - assert(current->held_monitor_count() == 0, "Should not be possible"); - // All monitors (including entered via JNI) have been unlocked above, so we need to clear jni count. - current->clear_jni_monitor_count(); } const char* ObjectSynchronizer::inflate_cause_name(const InflateCause cause) { diff --git a/src/hotspot/share/runtime/synchronizer.inline.hpp b/src/hotspot/share/runtime/synchronizer.inline.hpp index 6a850e5c8ca..cdbeb1daf5b 100644 --- a/src/hotspot/share/runtime/synchronizer.inline.hpp +++ b/src/hotspot/share/runtime/synchronizer.inline.hpp @@ -61,8 +61,6 @@ inline bool ObjectSynchronizer::quick_enter(oop obj, BasicLock* lock, JavaThread } inline void ObjectSynchronizer::exit(oop object, BasicLock* lock, JavaThread* current) { - current->dec_held_monitor_count(); - LightweightSynchronizer::exit(object, lock, current); } diff --git a/src/java.base/share/classes/jdk/internal/vm/Continuation.java b/src/java.base/share/classes/jdk/internal/vm/Continuation.java index a97f9ac9ea4..a7eb3ea6a9f 100644 --- a/src/java.base/share/classes/jdk/internal/vm/Continuation.java +++ b/src/java.base/share/classes/jdk/internal/vm/Continuation.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,7 +57,6 @@ public class Continuation { /** Reason for pinning */ public enum Pinned { /** Native frame on stack */ NATIVE, - /** Monitor held */ MONITOR, /** In critical section */ CRITICAL_SECTION, /** Exception (OOME/SOE) */ EXCEPTION } @@ -69,8 +68,7 @@ public class Continuation { /** Permanent failure: continuation already yielding */ PERM_FAIL_YIELDING(null), /** Permanent failure: continuation not mounted on the thread */ PERM_FAIL_NOT_MOUNTED(null), /** Transient failure: continuation pinned due to a held CS */ TRANSIENT_FAIL_PINNED_CRITICAL_SECTION(Pinned.CRITICAL_SECTION), - /** Transient failure: continuation pinned due to native frame */ TRANSIENT_FAIL_PINNED_NATIVE(Pinned.NATIVE), - /** Transient failure: continuation pinned due to a held monitor */ TRANSIENT_FAIL_PINNED_MONITOR(Pinned.MONITOR); + /** Transient failure: continuation pinned due to native frame */ TRANSIENT_FAIL_PINNED_NATIVE(Pinned.NATIVE); final Pinned pinned; private PreemptStatus(Pinned reason) { this.pinned = reason; } @@ -85,8 +83,7 @@ public class Continuation { return switch (reason) { case 2 -> Pinned.CRITICAL_SECTION; case 3 -> Pinned.NATIVE; - case 4 -> Pinned.MONITOR; - case 5 -> Pinned.EXCEPTION; + case 4 -> Pinned.EXCEPTION; default -> throw new AssertionError("Unknown pinned reason: " + reason); }; } From 59e87437b4f9259121710dca5e595ca714c3e71b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Roberto=20Casta=C3=B1eda=20Lozano?= Date: Mon, 6 Oct 2025 08:14:24 +0000 Subject: [PATCH 0069/1639] 8368753: IGV: improve CFG view of difference graphs Reviewed-by: chagedorn, mhaessig, dfenacci --- .../com/sun/hotspot/igv/data/InputBlock.java | 2 +- .../hotspot/igv/data/services/Scheduler.java | 10 ++-- .../hotspot/igv/difference/Difference.java | 9 ++++ .../ServerCompilerScheduler.java | 54 +++++++++++++------ 4 files changed, 54 insertions(+), 21 deletions(-) diff --git a/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/InputBlock.java b/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/InputBlock.java index 6670470b5e8..a5b282f9de1 100644 --- a/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/InputBlock.java +++ b/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/InputBlock.java @@ -135,7 +135,7 @@ public class InputBlock { successors.add(b); } - void setArtificial() { + public void setArtificial() { this.artificial = true; } diff --git a/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/services/Scheduler.java b/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/services/Scheduler.java index 1fe6ac3342a..4ff960f7c3d 100644 --- a/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/services/Scheduler.java +++ b/src/utils/IdealGraphVisualizer/Data/src/main/java/com/sun/hotspot/igv/data/services/Scheduler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,9 +24,7 @@ */ package com.sun.hotspot.igv.data.services; -import com.sun.hotspot.igv.data.InputBlock; import com.sun.hotspot.igv.data.InputGraph; -import java.util.Collection; /** * @@ -34,5 +32,9 @@ import java.util.Collection; */ public interface Scheduler { - public Collection schedule(InputGraph graph); + // Compute a set of scheduled blocks for the given graph, creating new + // blocks if these are not found in the graph. + public void schedule(InputGraph graph); + // Schedule locally the set of blocks in the given graph. + public void scheduleLocally(InputGraph graph); } diff --git a/src/utils/IdealGraphVisualizer/Difference/src/main/java/com/sun/hotspot/igv/difference/Difference.java b/src/utils/IdealGraphVisualizer/Difference/src/main/java/com/sun/hotspot/igv/difference/Difference.java index 89b1434663f..e3888be31be 100644 --- a/src/utils/IdealGraphVisualizer/Difference/src/main/java/com/sun/hotspot/igv/difference/Difference.java +++ b/src/utils/IdealGraphVisualizer/Difference/src/main/java/com/sun/hotspot/igv/difference/Difference.java @@ -114,6 +114,9 @@ public class Difference { Map blocksMap = new HashMap<>(); for (InputBlock blk : a.getBlocks()) { InputBlock diffblk = graph.addBlock(blk.getName()); + if (blk.isArtificial()) { + diffblk.setArtificial(); + } blocksMap.put(blk, diffblk); } for (InputBlock blk : b.getBlocks()) { @@ -121,6 +124,9 @@ public class Difference { if (diffblk == null) { diffblk = graph.addBlock(blk.getName()); } + if (blk.isArtificial()) { + diffblk.setArtificial(); + } blocksMap.put(blk, diffblk); } @@ -249,6 +255,9 @@ public class Difference { } } + Scheduler s = Lookup.getDefault().lookup(Scheduler.class); + s.scheduleLocally(graph); + return graph; } diff --git a/src/utils/IdealGraphVisualizer/ServerCompiler/src/main/java/com/sun/hotspot/igv/servercompiler/ServerCompilerScheduler.java b/src/utils/IdealGraphVisualizer/ServerCompiler/src/main/java/com/sun/hotspot/igv/servercompiler/ServerCompilerScheduler.java index 0a069c53a71..93199ea35a1 100644 --- a/src/utils/IdealGraphVisualizer/ServerCompiler/src/main/java/com/sun/hotspot/igv/servercompiler/ServerCompilerScheduler.java +++ b/src/utils/IdealGraphVisualizer/ServerCompiler/src/main/java/com/sun/hotspot/igv/servercompiler/ServerCompilerScheduler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -296,10 +296,25 @@ public class ServerCompilerScheduler implements Scheduler { return n.getProperties().get("block"); } + private boolean initialize(InputGraph graph) { + nodes = new ArrayList<>(); + inputNodeToNode = new HashMap<>(graph.getNodes().size()); + this.graph = graph; + if (!hasCategoryInformation()) { + ErrorManager.getDefault().log(ErrorManager.WARNING, + "Cannot find node category information in the input graph. " + + "The control-flow graph will not be approximated."); + return false; + } + buildUpGraph(); + markCFGNodes(); + return true; + } + @Override - public Collection schedule(InputGraph graph) { + public void schedule(InputGraph graph) { if (graph.getNodes().isEmpty()) { - return Collections.emptyList(); + return; } if (graph.getBlocks().size() > 0) { @@ -311,20 +326,11 @@ public class ServerCompilerScheduler implements Scheduler { assert graph.getBlock(n) != null; } } - return graph.getBlocks(); + return; } else { - nodes = new ArrayList<>(); - inputNodeToNode = new HashMap<>(graph.getNodes().size()); - - this.graph = graph; - if (!hasCategoryInformation()) { - ErrorManager.getDefault().log(ErrorManager.WARNING, - "Cannot find node category information in the input graph. " + - "The control-flow graph will not be approximated."); - return null; + if (!initialize(graph)) { + return; } - buildUpGraph(); - markCFGNodes(); buildBlocks(); schedulePinned(); buildDominators(); @@ -333,10 +339,26 @@ public class ServerCompilerScheduler implements Scheduler { check(); reportWarnings(); - return blocks; + return; } } + @Override + public void scheduleLocally(InputGraph graph) { + if (!initialize(graph)) { + return; + } + // Import global schedule from the given graph. + blocks = new Vector<>(); + for (InputBlock block : graph.getBlocks()) { + blocks.add(block); + for (InputNode in : block.getNodes()) { + inputNodeToNode.get(in).block = block; + } + } + scheduleLocal(); + } + private void scheduleLocal() { // Leave only local predecessors and successors. for (InputBlock b : blocks) { From baf8bc5701c43425e3345f82d4318b134b26d7c9 Mon Sep 17 00:00:00 2001 From: Francesco Andreuzzi Date: Mon, 6 Oct 2025 08:14:44 +0000 Subject: [PATCH 0070/1639] 8369038: Parallel: Use NMethodMarkingScope and ThreadsClaimTokenScope in psParallelCompact Reviewed-by: ayang, shade --- src/hotspot/share/gc/parallel/psParallelCompact.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/gc/parallel/psParallelCompact.cpp b/src/hotspot/share/gc/parallel/psParallelCompact.cpp index af812c652a6..5affa1a3e35 100644 --- a/src/hotspot/share/gc/parallel/psParallelCompact.cpp +++ b/src/hotspot/share/gc/parallel/psParallelCompact.cpp @@ -28,6 +28,7 @@ #include "classfile/symbolTable.hpp" #include "classfile/systemDictionary.hpp" #include "code/codeCache.hpp" +#include "code/nmethod.hpp" #include "compiler/oopMap.hpp" #include "gc/parallel/objectStartArray.inline.hpp" #include "gc/parallel/parallelArguments.hpp" @@ -61,7 +62,6 @@ #include "gc/shared/referenceProcessor.hpp" #include "gc/shared/referenceProcessorPhaseTimes.hpp" #include "gc/shared/spaceDecorator.hpp" -#include "gc/shared/strongRootsScope.hpp" #include "gc/shared/taskTerminator.hpp" #include "gc/shared/weakProcessor.inline.hpp" #include "gc/shared/workerPolicy.hpp" @@ -1085,7 +1085,8 @@ void steal_marking_work(TaskTerminator& terminator, uint worker_id) { } class MarkFromRootsTask : public WorkerTask { - StrongRootsScope _strong_roots_scope; // needed for Threads::possibly_parallel_threads_do + NMethodMarkingScope _nmethod_marking_scope; + ThreadsClaimTokenScope _threads_claim_token_scope; OopStorageSetStrongParState _oop_storage_set_par_state; TaskTerminator _terminator; uint _active_workers; @@ -1093,7 +1094,8 @@ class MarkFromRootsTask : public WorkerTask { public: MarkFromRootsTask(uint active_workers) : WorkerTask("MarkFromRootsTask"), - _strong_roots_scope(active_workers), + _nmethod_marking_scope(), + _threads_claim_token_scope(), _terminator(active_workers, ParCompactionManager::marking_stacks()), _active_workers(active_workers) {} From 2c114d676d9904094dd6058d15f06d801ec7a3d6 Mon Sep 17 00:00:00 2001 From: SendaoYan Date: Mon, 6 Oct 2025 09:26:51 +0000 Subject: [PATCH 0071/1639] 8367899: compiler/c2/gvn/TestBitCompressValueTransform.java intermittent timed out Reviewed-by: dfenacci, chagedorn --- .../c2/gvn/TestBitCompressValueTransform.java | 49 ++++++++----------- 1 file changed, 20 insertions(+), 29 deletions(-) diff --git a/test/hotspot/jtreg/compiler/c2/gvn/TestBitCompressValueTransform.java b/test/hotspot/jtreg/compiler/c2/gvn/TestBitCompressValueTransform.java index 98f26f120b1..3f32f78871c 100644 --- a/test/hotspot/jtreg/compiler/c2/gvn/TestBitCompressValueTransform.java +++ b/test/hotspot/jtreg/compiler/c2/gvn/TestBitCompressValueTransform.java @@ -76,10 +76,7 @@ public class TestBitCompressValueTransform { @Run(test = "test1") public void run1(RunInfo info) { - long res = 0; - for (int i = 0; i < 10000; i++) { - res |= test1(field_L); - } + long res = test1(field_L); Asserts.assertEQ(res, gold_L); } @@ -92,10 +89,7 @@ public class TestBitCompressValueTransform { @Run(test = "test2") public void run2(RunInfo info) { - int res = 0; - for (int i = 0; i < 10000; i++) { - res |= test2(field_I); - } + int res = test2(field_I); Asserts.assertEQ(res, gold_I); } @@ -113,7 +107,7 @@ public class TestBitCompressValueTransform { @Run(test = "test3") public void run3(RunInfo info) { int res = 0; - for (int i = 1; i < 10000; i++) { + for (int i = 1; i < 100; i++) { res |= test3(i); } Asserts.assertLTE(0, res); @@ -133,7 +127,7 @@ public class TestBitCompressValueTransform { @Run(test = "test4") public void run4(RunInfo info) { long res = 0; - for (long i = 1; i < 10000; i++) { + for (long i = 1; i < 100; i++) { res |= test4(i); } Asserts.assertLTE(0L, res); @@ -151,7 +145,7 @@ public class TestBitCompressValueTransform { @Run(test = "test5") public void run5(RunInfo info) { long res = 0; - for (int i = -10000; i < 10000; i++) { + for (int i = -100; i < 100; i++) { res |= test5((long)i); } Asserts.assertEQ(-1L, res); @@ -169,7 +163,7 @@ public class TestBitCompressValueTransform { @Run(test = "test6") public void run6(RunInfo info) { long res = 0; - for (int i = -10000; i < 10000; i++) { + for (int i = -100; i < 100; i++) { res |= test6((long)i); } Asserts.assertLTE(0L, res); @@ -188,7 +182,7 @@ public class TestBitCompressValueTransform { @Run(test = "test7") public void run7(RunInfo info) { long res = Long.MIN_VALUE; - for (int i = -10000; i < 10000; i++) { + for (int i = -100; i < 100; i++) { res = Long.max(test7((long)i), res); } Asserts.assertGTE(10000L, res); @@ -206,7 +200,7 @@ public class TestBitCompressValueTransform { @Run(test = "test8") public void run8(RunInfo info) { int res = 0; - for (int i = -10000; i < 10000; i++) { + for (int i = -100; i < 100; i++) { res |= test8(i); } Asserts.assertEQ(-1, res); @@ -224,7 +218,7 @@ public class TestBitCompressValueTransform { @Run(test = "test9") public void run9(RunInfo info) { int res = 0; - for (int i = -10000; i < 10000; i++) { + for (int i = -100; i < 100; i++) { res |= test9(i); } Asserts.assertLTE(0, res); @@ -243,10 +237,10 @@ public class TestBitCompressValueTransform { @Run(test = "test10") public void run10(RunInfo info) { int res = Integer.MIN_VALUE; - for (int i = -10000; i < 10000; i++) { + for (int i = -100; i < 100; i++) { res = Integer.max(test10(i), res); } - Asserts.assertGTE(10000, res); + Asserts.assertGTE(100, res); } @Test @@ -260,7 +254,7 @@ public class TestBitCompressValueTransform { @Run(test = "test11") public void run11(RunInfo info) { int res = 0; - for (int i = -10000; i < 10000; i++) { + for (int i = -100; i < 100; i++) { res |= test11(i); } Asserts.assertEQ(0, res); @@ -277,7 +271,7 @@ public class TestBitCompressValueTransform { @Run(test = "test12") public void run12(RunInfo info) { long res = 0; - for (int i = -10000; i < 10000; i++) { + for (int i = -100; i < 100; i++) { res |= test12(i); } Asserts.assertEQ(0L, res); @@ -294,7 +288,7 @@ public class TestBitCompressValueTransform { @Run(test = "test13") public void run13(RunInfo info) { int res = 0; - for (int i = -10000; i < 10000; i++) { + for (int i = -100; i < 100; i++) { res |= test13(i); } Asserts.assertEQ(0, res); @@ -311,7 +305,7 @@ public class TestBitCompressValueTransform { @Run(test = "test14") public void run14(RunInfo info) { long res = 0; - for (int i = -10000; i < 10000; i++) { + for (int i = -100; i < 100; i++) { res |= test14(i); } Asserts.assertEQ(0L, res); @@ -327,10 +321,7 @@ public class TestBitCompressValueTransform { @Run (test = "test15") public void run15(RunInfo info) { - int res = 0; - for (int i = 0; i < 10000; i++) { - res |= test15(0, 0); - } + int res = test15(0, 0); Asserts.assertEQ(0, res); } @@ -408,7 +399,7 @@ public class TestBitCompressValueTransform { int actual = 0; int expected = 0; - for (int i = 0; i < 10000; i++) { + for (int i = 0; i < 100; i++) { int arg1 = GEN_I.next(); int arg2 = GEN_I.next(); @@ -492,7 +483,7 @@ public class TestBitCompressValueTransform { int actual = 0; int expected = 0; - for (int i = 0; i < 10000; i++) { + for (int i = 0; i < 100; i++) { int arg1 = GEN_I.next(); int arg2 = GEN_I.next(); @@ -576,7 +567,7 @@ public class TestBitCompressValueTransform { long actual = 0; long expected = 0; - for (int i = 0; i < 10000; i++) { + for (int i = 0; i < 100; i++) { long arg1 = GEN_L.next(); long arg2 = GEN_L.next(); @@ -660,7 +651,7 @@ public class TestBitCompressValueTransform { long actual = 0; long expected = 0; - for (int i = 0; i < 10000; i++) { + for (int i = 0; i < 100; i++) { long arg1 = GEN_L.next(); long arg2 = GEN_L.next(); From 2bfada3f58df6c041d948267368cbc4db915cac3 Mon Sep 17 00:00:00 2001 From: jonghoonpark Date: Mon, 6 Oct 2025 11:53:14 +0000 Subject: [PATCH 0072/1639] 8364927: Add @requires annotation to TestReclaimStringsLeaksMemory.java Reviewed-by: tschatzl, stefank, ayang --- .../stress/TestReclaimStringsLeaksMemory.java | 49 +++++++++++++++++-- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/test/hotspot/jtreg/gc/stress/TestReclaimStringsLeaksMemory.java b/test/hotspot/jtreg/gc/stress/TestReclaimStringsLeaksMemory.java index 80ab9e21667..1f19222fb8e 100644 --- a/test/hotspot/jtreg/gc/stress/TestReclaimStringsLeaksMemory.java +++ b/test/hotspot/jtreg/gc/stress/TestReclaimStringsLeaksMemory.java @@ -24,19 +24,60 @@ package gc.stress; /* - * @test TestReclaimStringsLeaksMemory + * @test id=Serial * @bug 8180048 - * @summary Ensure that during a Full GC interned string memory is reclaimed completely. - * @requires vm.gc == "null" + * @summary Ensure that during a Full GC interned string memory is reclaimed completely with SerialGC. + * @requires vm.gc.Serial * @requires !vm.debug * @library /test/lib * @modules java.base/jdk.internal.misc - * @run driver/timeout=480 gc.stress.TestReclaimStringsLeaksMemory * @run driver/timeout=480 gc.stress.TestReclaimStringsLeaksMemory -XX:+UseSerialGC + */ + +/* + * @test id=Parallel + * @bug 8180048 + * @summary Ensure that during a Full GC interned string memory is reclaimed completely with ParallelGC. + * @requires vm.gc.Parallel + * @requires !vm.debug + * @library /test/lib + * @modules java.base/jdk.internal.misc * @run driver/timeout=480 gc.stress.TestReclaimStringsLeaksMemory -XX:+UseParallelGC + */ + +/* + * @test id=G1 + * @bug 8180048 + * @summary Ensure that during a Full GC interned string memory is reclaimed completely with G1GC. + * @requires vm.gc.G1 + * @requires !vm.debug + * @library /test/lib + * @modules java.base/jdk.internal.misc * @run driver/timeout=480 gc.stress.TestReclaimStringsLeaksMemory -XX:+UseG1GC */ +/* + * @test id=Shenandoah + * @bug 8180048 + * @summary Ensure that during a Full GC interned string memory is reclaimed completely with ShenandoahGC. + * @requires vm.gc.Shenandoah + * @requires !vm.debug + * @library /test/lib + * @modules java.base/jdk.internal.misc + * @run driver/timeout=480 gc.stress.TestReclaimStringsLeaksMemory -XX:+UseShenandoahGC + */ + +/* + * @test id=Z + * @bug 8180048 + * @summary Ensure that during a Full GC interned string memory is reclaimed completely with ZGC. + * @requires vm.gc.Z + * @requires !vm.debug + * @library /test/lib + * @modules java.base/jdk.internal.misc + * @run driver/timeout=480 gc.stress.TestReclaimStringsLeaksMemory -XX:+UseZGC + */ + import java.util.Arrays; import java.util.ArrayList; import java.util.regex.Pattern; From e3320a9df592a06c466ae9158d8f173921679952 Mon Sep 17 00:00:00 2001 From: Nizar Benalla Date: Mon, 6 Oct 2025 13:32:46 +0000 Subject: [PATCH 0073/1639] 8367610: Test tools/sincechecker/modules/java.base/JavaBaseCheckSince.java timed out on Windows Reviewed-by: liach --- .../sincechecker/modules/java.base/JavaBaseCheckSince.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/jdk/tools/sincechecker/modules/java.base/JavaBaseCheckSince.java b/test/jdk/tools/sincechecker/modules/java.base/JavaBaseCheckSince.java index 64d5bf2465f..b75b6d9401a 100644 --- a/test/jdk/tools/sincechecker/modules/java.base/JavaBaseCheckSince.java +++ b/test/jdk/tools/sincechecker/modules/java.base/JavaBaseCheckSince.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,8 +23,8 @@ /* * @test - * @bug 8331051 + * @bug 8331051 8367610 * @summary Test for `@since` in java.base module * @library /test/lib /test/jdk/tools/sincechecker - * @run main SinceChecker java.base --exclude java.lang.classfile + * @run main/timeout=480 SinceChecker java.base --exclude java.lang.classfile */ From b6a4cfecb731615b6ef70828ac10fae4b2264cdc Mon Sep 17 00:00:00 2001 From: Mahendra Chhipa Date: Mon, 6 Oct 2025 15:26:59 +0000 Subject: [PATCH 0074/1639] 8367114: Update jdk.test.lib.net.SimpleHttpServer to use SimpleFileServer Reviewed-by: dfuchs, vyazici --- .../catalog/CatalogFileInputTest.java | 27 +++- .../sun/net/httpserver/SimpleFileServer.java | 71 -------- .../mrjar/MultiReleaseJarHttpProperties.java | 27 ++-- .../jar/MultiReleaseJarURLConnection.java | 27 ++-- .../jdk/test/lib/net/SimpleHttpServer.java | 152 ------------------ 5 files changed, 53 insertions(+), 251 deletions(-) delete mode 100644 test/jdk/com/sun/net/httpserver/SimpleFileServer.java delete mode 100644 test/lib/jdk/test/lib/net/SimpleHttpServer.java diff --git a/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogFileInputTest.java b/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogFileInputTest.java index 66ddad86785..9a19c0237d7 100644 --- a/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogFileInputTest.java +++ b/test/jaxp/javax/xml/jaxp/unittest/catalog/CatalogFileInputTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,6 +38,8 @@ import java.net.URI; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import javax.xml.catalog.Catalog; import javax.xml.catalog.CatalogException; @@ -49,6 +51,9 @@ import static java.nio.file.StandardOpenOption.APPEND; import static java.nio.file.StandardOpenOption.CREATE; import static jaxp.library.JAXPTestUtilities.getSystemProperty; +import com.sun.net.httpserver.HttpServer; +import com.sun.net.httpserver.SimpleFileServer; +import jdk.test.lib.net.URIBuilder; import jdk.test.lib.util.JarUtils; import org.testng.Assert; import org.testng.annotations.AfterClass; @@ -56,13 +61,11 @@ import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import org.xml.sax.InputSource; -import jdk.test.lib.net.SimpleHttpServer; /* * @test * @bug 8151154 8171243 * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest /test/lib - * @build jdk.test.lib.net.SimpleHttpServer * @run testng/othervm catalog.CatalogFileInputTest * @summary Verifies that the Catalog API accepts valid URIs only; * Verifies that the CatalogFeatures' builder throws @@ -81,9 +84,9 @@ public class CatalogFileInputTest extends CatalogSupportBase { final static String SCHEME_JARFILE = "jar:"; static final String REMOTE_FILE_LOCATION = "/jar/META-INF"; static final String DOCROOT = SRC_DIR; - static final String TESTCONTEXT = REMOTE_FILE_LOCATION; //mapped to local file path - private SimpleHttpServer httpserver; + private HttpServer httpserver; private String remoteFilePath; + private ExecutorService executor; /* * Initializing fields @@ -92,15 +95,23 @@ public class CatalogFileInputTest extends CatalogSupportBase { public void setUpClass() throws Exception { super.setUp(); // set up HttpServer - httpserver = new SimpleHttpServer(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), TESTCONTEXT, DOCROOT); + httpserver = SimpleFileServer.createFileServer(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), + Path.of(DOCROOT), SimpleFileServer.OutputLevel.INFO); + executor = Executors.newCachedThreadPool(); + httpserver.setExecutor(executor); httpserver.start(); - remoteFilePath = httpserver.getAddress() + REMOTE_FILE_LOCATION; + remoteFilePath = URIBuilder.newBuilder() + .scheme("http") + .host(httpserver.getAddress().getAddress()) + .port(httpserver.getAddress().getPort()) + .build().toString() + REMOTE_FILE_LOCATION; } @AfterClass protected void tearDown() { if (httpserver != null) { - httpserver.stop(); + httpserver.stop(0); + executor.shutdown(); } } diff --git a/test/jdk/com/sun/net/httpserver/SimpleFileServer.java b/test/jdk/com/sun/net/httpserver/SimpleFileServer.java deleted file mode 100644 index bff415c0b98..00000000000 --- a/test/jdk/com/sun/net/httpserver/SimpleFileServer.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.util.concurrent.*; -import java.util.logging.*; -import java.io.*; -import java.net.*; - -import com.sun.net.httpserver.*; - -/** - * Implements a basic static content HTTP server - * which understands text/html, text/plain content types - * - * Must be given an abs pathname to the document root. - * Directory listings together with text + html files - * can be served. - * - * File Server created on files sub-path - * - * Echo server created on echo sub-path - */ -public class SimpleFileServer { - - public static void main (String[] args) throws Exception { - if (args.length != 3) { - System.out.println ("usage: java FileServerHandler rootDir port logfilename"); - System.exit(1); - } - Logger logger = Logger.getLogger("com.sun.net.httpserver"); - ConsoleHandler ch = new ConsoleHandler(); - logger.setLevel(Level.ALL); - ch.setLevel(Level.ALL); - logger.addHandler(ch); - - String rootDir = args[0]; - int port = Integer.parseInt (args[1]); - String logfile = args[2]; - HttpServer server = HttpServer.create (new InetSocketAddress (port), 0); - HttpHandler h = new FileServerHandler (rootDir); - HttpHandler h1 = new EchoHandler (); - - HttpContext c = server.createContext ("/files", h); - c.getFilters().add (new LogFilter (new File (logfile))); - HttpContext c1 = server.createContext ("/echo", h1); - c.getFilters().add (new LogFilter (new File (logfile))); - c1.getFilters().add (new LogFilter (new File (logfile))); - server.setExecutor (Executors.newCachedThreadPool()); - server.start (); - } -} diff --git a/test/jdk/java/util/jar/JarFile/mrjar/MultiReleaseJarHttpProperties.java b/test/jdk/java/util/jar/JarFile/mrjar/MultiReleaseJarHttpProperties.java index 93cf0e0165d..16f764c6674 100644 --- a/test/jdk/java/util/jar/JarFile/mrjar/MultiReleaseJarHttpProperties.java +++ b/test/jdk/java/util/jar/JarFile/mrjar/MultiReleaseJarHttpProperties.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,9 +28,7 @@ * @library /lib/testlibrary/java/util/jar /test/lib * @modules jdk.jartool * jdk.compiler - * jdk.httpserver * @build CreateMultiReleaseTestJars - * jdk.test.lib.net.SimpleHttpServer * jdk.test.lib.compiler.Compiler * jdk.test.lib.util.JarBuilder * @run testng MultiReleaseJarHttpProperties @@ -51,21 +49,28 @@ import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.URL; import java.net.URLClassLoader; +import java.nio.file.Path; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; -import jdk.test.lib.net.SimpleHttpServer; +import com.sun.net.httpserver.HttpServer; +import com.sun.net.httpserver.SimpleFileServer; import jdk.test.lib.net.URIBuilder; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; public class MultiReleaseJarHttpProperties extends MultiReleaseJarProperties { - private SimpleHttpServer server; + private HttpServer server; + private ExecutorService executor; static final String TESTCONTEXT = "/multi-release.jar"; //mapped to local file path @BeforeClass public void initialize() throws Exception { - server = new SimpleHttpServer(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), TESTCONTEXT, - System.getProperty("user.dir", ".")); + server = SimpleFileServer.createFileServer(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), + Path.of(System.getProperty("user.dir", ".")), SimpleFileServer.OutputLevel.INFO); + executor = Executors.newCachedThreadPool(); + server.setExecutor(executor); server.start(); super.initialize(); } @@ -73,7 +78,7 @@ public class MultiReleaseJarHttpProperties extends MultiReleaseJarProperties { @Override protected void initializeClassLoader() throws Exception { URL[] urls = new URL[]{ - URIBuilder.newBuilder().scheme("http").port(server.getPort()).loopback() + URIBuilder.newBuilder().scheme("http").port(server.getAddress().getPort()).loopback() .path(TESTCONTEXT).toURL(), }; cldr = new URLClassLoader(urls); @@ -84,8 +89,10 @@ public class MultiReleaseJarHttpProperties extends MultiReleaseJarProperties { @AfterClass public void close() throws IOException { // Windows requires server to stop before file is deleted - if (server != null) - server.stop(); + if (server != null) { + server.stop(0); + executor.shutdown(); + } super.close(); } diff --git a/test/jdk/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java b/test/jdk/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java index 2d5ba81194f..f113e7d3fcd 100644 --- a/test/jdk/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java +++ b/test/jdk/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,10 +27,8 @@ * @summary Test that URL connections to multi-release jars can be runtime versioned * @library /lib/testlibrary/java/util/jar /test/lib * @modules jdk.compiler - * jdk.httpserver * jdk.jartool * @build CreateMultiReleaseTestJars - * jdk.test.lib.net.SimpleHttpServer * jdk.test.lib.util.JarBuilder * jdk.test.lib.compiler.Compiler * @run testng MultiReleaseJarURLConnection @@ -51,11 +49,15 @@ import java.net.URL; import java.net.URLClassLoader; import java.net.URLConnection; import java.nio.file.Files; +import java.nio.file.Path; import java.nio.file.Paths; import java.util.Enumeration; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.jar.JarFile; -import jdk.test.lib.net.SimpleHttpServer; +import com.sun.net.httpserver.HttpServer; +import com.sun.net.httpserver.SimpleFileServer; import jdk.test.lib.net.URIBuilder; import org.testng.Assert; import org.testng.annotations.AfterClass; @@ -68,8 +70,8 @@ public class MultiReleaseJarURLConnection { String unversioned = userdir + "/unversioned.jar"; String unsigned = userdir + "/multi-release.jar"; String signed = userdir + "/signed-multi-release.jar"; - static final String TESTCONTEXT = "/multi-release.jar"; - SimpleHttpServer server; + HttpServer server; + ExecutorService executor; @BeforeClass public void initialize() throws Exception { @@ -78,7 +80,10 @@ public class MultiReleaseJarURLConnection { creator.buildUnversionedJar(); creator.buildMultiReleaseJar(); creator.buildSignedMultiReleaseJar(); - server = new SimpleHttpServer(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), TESTCONTEXT, System.getProperty("user.dir", ".")); + server = SimpleFileServer.createFileServer(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0), + Path.of(System.getProperty("user.dir", ".")), SimpleFileServer.OutputLevel.INFO); + executor = Executors.newCachedThreadPool(); + server.setExecutor(executor); server.start(); } @@ -86,7 +91,9 @@ public class MultiReleaseJarURLConnection { public void close() throws IOException { // Windows requires server to stop before file is deleted if (server != null) - server.stop(); + server.stop(0); + executor.shutdown(); + Files.delete(Paths.get(unversioned)); Files.delete(Paths.get(unsigned)); Files.delete(Paths.get(signed)); @@ -176,8 +183,8 @@ public class MultiReleaseJarURLConnection { {"unsigned", new URL("jar:file:" + unsigned + "!/")}, {"signed", new URL("jar:file:" + signed + "!/")}, // external jar received via http protocol - {"http", toHttpJarURL(server.getPort(), "/multi-release.jar", "!/")}, - {"http", URIBuilder.newBuilder().scheme("http").port(server.getPort()) + {"http", toHttpJarURL(server.getAddress().getPort(), "/multi-release.jar", "!/")}, + {"http", URIBuilder.newBuilder().scheme("http").port(server.getAddress().getPort()) .loopback().path("/multi-release.jar").toURL()}, }; } diff --git a/test/lib/jdk/test/lib/net/SimpleHttpServer.java b/test/lib/jdk/test/lib/net/SimpleHttpServer.java deleted file mode 100644 index 1905091eac6..00000000000 --- a/test/lib/jdk/test/lib/net/SimpleHttpServer.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package jdk.test.lib.net; - -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.InetSocketAddress; -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.file.FileSystemNotFoundException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import com.sun.net.httpserver.Headers; -import com.sun.net.httpserver.HttpExchange; -import com.sun.net.httpserver.HttpHandler; -import com.sun.net.httpserver.HttpServer; - -/** - * A simple HTTP Server. - **/ -public class SimpleHttpServer { - private final HttpServer httpServer; - private ExecutorService executor; - private String address; - private final String context; - private final String docRoot; - private final InetSocketAddress inetSocketAddress; - - public SimpleHttpServer(final InetSocketAddress inetSocketAddress, final String context, final String docRoot) - throws IOException { - this.inetSocketAddress = inetSocketAddress; - this.context = context; - this.docRoot = docRoot; - httpServer = HttpServer.create(); - } - - public void start() throws IOException, URISyntaxException { - MyHttpHandler handler = new MyHttpHandler(docRoot); - httpServer.bind(inetSocketAddress, 0); - httpServer.createContext(context, handler); - executor = Executors.newCachedThreadPool(); - httpServer.setExecutor(executor); - httpServer.start(); - address = "http:" + URIBuilder.newBuilder().host(httpServer.getAddress().getAddress()). - port(httpServer.getAddress().getPort()).build().toString(); - } - - public void stop() { - httpServer.stop(0); - executor.shutdown(); - } - - public String getAddress() { - return address; - } - - public int getPort() { - return httpServer.getAddress().getPort(); - } - - class MyHttpHandler implements HttpHandler { - private final URI rootUri; - - MyHttpHandler(final String docroot) { - rootUri = Path.of(docroot).toUri().normalize(); - } - - public void handle(final HttpExchange t) throws IOException { - try (InputStream is = t.getRequestBody()) { - is.readAllBytes(); - Headers rMap = t.getResponseHeaders(); - try (OutputStream os = t.getResponseBody()) { - URI uri = t.getRequestURI(); - String path = uri.getRawPath(); - assert path.isEmpty() || path.startsWith("/"); - Path fPath; - try { - uri = URI.create("file://" + rootUri.getRawPath() + path).normalize(); - fPath = Path.of(uri); - } catch (IllegalArgumentException | FileSystemNotFoundException ex) { - ex.printStackTrace(); - notfound(t, path); - return; - } - byte[] bytes = Files.readAllBytes(fPath); - String method = t.getRequestMethod(); - if (method.equals("HEAD")) { - rMap.set("Content-Length", Long.toString(bytes.length)); - t.sendResponseHeaders(200, -1); - t.close(); - } else if (!method.equals("GET")) { - t.sendResponseHeaders(405, -1); - t.close(); - return; - } - if (path.endsWith(".html") || path.endsWith(".htm")) { - rMap.set("Content-Type", "text/html"); - } else { - rMap.set("Content-Type", "text/plain"); - } - t.sendResponseHeaders(200, bytes.length); - os.write(bytes); - } - } - } - void moved(final HttpExchange t) throws IOException { - Headers req = t.getRequestHeaders(); - Headers map = t.getResponseHeaders(); - URI uri = t.getRequestURI(); - String host = req.getFirst("Host"); - String location = "http://" + host + uri.getPath() + "/"; - map.set("Content-Type", "text/html"); - map.set("Location", location); - t.sendResponseHeaders(301, -1); - t.close(); - } - void notfound(final HttpExchange t, final String p) throws IOException { - t.getResponseHeaders().set("Content-Type", "text/html"); - t.sendResponseHeaders(404, 0); - try (OutputStream os = t.getResponseBody()) { - String s = "

File not found

"; - s = s + p + "

"; - os.write(s.getBytes()); - } - t.close(); - } - } -} From 596af0a7cc37e359d54689be20f855a86ae46567 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Mon, 6 Oct 2025 15:44:13 +0000 Subject: [PATCH 0075/1639] 8369041: Release memory after testing in ThreadsRunner.java Reviewed-by: shade, tschatzl --- .../jtreg/vmTestbase/nsk/share/runner/ThreadsRunner.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/runner/ThreadsRunner.java b/test/hotspot/jtreg/vmTestbase/nsk/share/runner/ThreadsRunner.java index 0401fea13fc..39e7e2c2237 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/runner/ThreadsRunner.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/runner/ThreadsRunner.java @@ -310,6 +310,10 @@ public class ThreadsRunner implements MultiRunner, LogAware, RunParamsAware { log.info("Unexpected exception during the run."); log.info(t); successful = false; + } finally { + // Finished testing; release memory to avoid OOM. + runnables.clear(); + threads.clear(); } } From 0f406c420e35f7a4358dc99711fd23d162f21777 Mon Sep 17 00:00:00 2001 From: Justin Lu Date: Mon, 6 Oct 2025 16:11:59 +0000 Subject: [PATCH 0076/1639] 8369078: Fix faulty test conversion in IllegalCharsetName.java Reviewed-by: naoto, alanb --- test/jdk/java/nio/charset/Charset/IllegalCharsetName.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/jdk/java/nio/charset/Charset/IllegalCharsetName.java b/test/jdk/java/nio/charset/Charset/IllegalCharsetName.java index 266801cf52b..9f2879a3ff0 100644 --- a/test/jdk/java/nio/charset/Charset/IllegalCharsetName.java +++ b/test/jdk/java/nio/charset/Charset/IllegalCharsetName.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,7 +50,7 @@ public class IllegalCharsetName { assertThrows(IllegalCharsetNameException.class, () -> Charset.forName(name)); assertThrows(IllegalCharsetNameException.class, - () -> Charset.forName(name)); + () -> Charset.isSupported(name)); } // Charset.forName, Charset.isSupported, and the Charset constructor should @@ -60,7 +60,7 @@ public class IllegalCharsetName { assertThrows(IllegalCharsetNameException.class, () -> Charset.forName("")); assertThrows(IllegalCharsetNameException.class, - () -> Charset.forName("")); + () -> Charset.isSupported("")); assertThrows(IllegalCharsetNameException.class, () -> new Charset("", new String[]{}) { @Override From 2376a9e9727e9cb3020dd3f57584950a4cdcdab6 Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Mon, 6 Oct 2025 17:30:42 +0000 Subject: [PATCH 0077/1639] 8365630: jdk/jfr/tool/TestPrintContextual.java fails with wrong spanId Reviewed-by: shade --- test/jdk/jdk/jfr/tool/TestPrintContextual.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/test/jdk/jdk/jfr/tool/TestPrintContextual.java b/test/jdk/jdk/jfr/tool/TestPrintContextual.java index 15486148b9c..e6df9c7c729 100644 --- a/test/jdk/jdk/jfr/tool/TestPrintContextual.java +++ b/test/jdk/jdk/jfr/tool/TestPrintContextual.java @@ -25,6 +25,7 @@ package jdk.jfr.tool; import java.nio.file.Files; import java.nio.file.Path; +import java.time.Instant; import java.util.AbstractMap; import java.util.ArrayList; import java.util.List; @@ -264,7 +265,8 @@ public class TestPrintContextual { } } - private static void span(int depth) { + private static void span(int depth) throws InterruptedException { + awaitUniqueTimestamp(); SpanEvent span = new SpanEvent(); span.name = "span"; span.spanId = depth; @@ -277,6 +279,13 @@ public class TestPrintContextual { span.commit(); } + private static void awaitUniqueTimestamp() throws InterruptedException { + Instant timestamp = Instant.now(); + while (timestamp.equals(Instant.now())) { + Thread.sleep(1); + } + } + // Tests that context values are only inhjected into events in the same thread. private static void testThreadedContext() throws Exception { try (Recording r = new Recording()) { From eb34a117934951af075a425ce2cf8d3b1ced9700 Mon Sep 17 00:00:00 2001 From: Mikael Vidstedt Date: Tue, 7 Oct 2025 00:52:38 +0000 Subject: [PATCH 0078/1639] 8369242: Rename URL variables in devkit/Tools.gmk Reviewed-by: erikj --- make/devkit/Tools.gmk | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/make/devkit/Tools.gmk b/make/devkit/Tools.gmk index f27d47b822c..6241674071c 100644 --- a/make/devkit/Tools.gmk +++ b/make/devkit/Tools.gmk @@ -117,13 +117,13 @@ dependencies := gcc binutils ccache mpfr gmp mpc gdb $(foreach dep,$(dependencies),$(eval $(dep)_ver := $(dep)-$($(dep)_ver_only))) -GCC := http://ftp.gnu.org/pub/gnu/gcc/$(gcc_ver)/$(gcc_ver).tar.xz -BINUTILS := http://ftp.gnu.org/pub/gnu/binutils/$(binutils_ver).tar.gz -CCACHE := https://github.com/ccache/ccache/releases/download/v$(ccache_ver_only)/$(ccache_ver).tar.xz -MPFR := https://www.mpfr.org/$(mpfr_ver)/$(mpfr_ver).tar.bz2 -GMP := http://ftp.gnu.org/pub/gnu/gmp/$(gmp_ver).tar.bz2 -MPC := http://ftp.gnu.org/pub/gnu/mpc/$(mpc_ver).tar.gz -GDB := http://ftp.gnu.org/gnu/gdb/$(gdb_ver).tar.xz +GCC_URL := http://ftp.gnu.org/pub/gnu/gcc/$(gcc_ver)/$(gcc_ver).tar.xz +BINUTILS_URL := http://ftp.gnu.org/pub/gnu/binutils/$(binutils_ver).tar.gz +CCACHE_URL := https://github.com/ccache/ccache/releases/download/v$(ccache_ver_only)/$(ccache_ver).tar.xz +MPFR_URL := https://www.mpfr.org/$(mpfr_ver)/$(mpfr_ver).tar.bz2 +GMP_URL := http://ftp.gnu.org/pub/gnu/gmp/$(gmp_ver).tar.bz2 +MPC_URL := http://ftp.gnu.org/pub/gnu/mpc/$(mpc_ver).tar.gz +GDB_URL := http://ftp.gnu.org/gnu/gdb/$(gdb_ver).tar.xz REQUIRED_MIN_MAKE_MAJOR_VERSION := 4 ifneq ($(REQUIRED_MIN_MAKE_MAJOR_VERSION),) @@ -201,7 +201,7 @@ download-rpms: # Generate downloading + unpacking of sources. define Download # Allow override - $(1)_DIRNAME ?= $(basename $(basename $(notdir $($(1))))) + $(1)_DIRNAME ?= $(basename $(basename $(notdir $($(1)_URL)))) $(1)_DIR = $(abspath $(SRCDIR)/$$($(1)_DIRNAME)) ifeq ($$($(1)_CMAKE_BASED),) $(1)_CFG = $$($(1)_DIR)/configure @@ -212,7 +212,7 @@ define Download $(1)_SRC_MARKER = $$($(1)_DIR)/CMakeLists.txt $(1)_CONFIG = $$(CMAKE_CONFIG) $$($(1)_DIR) endif - $(1)_FILE = $(DOWNLOAD)/$(notdir $($(1))) + $(1)_FILE = $(DOWNLOAD)/$(notdir $($(1)_URL)) $$($(1)_SRC_MARKER) : $$($(1)_FILE) mkdir -p $$(SRCDIR) @@ -224,7 +224,7 @@ define Download touch $$@ $$($(1)_FILE) : - wget -P $(DOWNLOAD) $$($(1)) + wget -P $(DOWNLOAD) $$($(1)_URL) endef # Download and unpack all source packages From e783c524c17e1d1a3fff4b6370e222134e66edc8 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Tue, 7 Oct 2025 04:08:32 +0000 Subject: [PATCH 0079/1639] 8368185: Test javax/swing/plaf/synth/SynthButtonUI/6276188/bug6276188.java failed: Synth ButtonUI does not handle PRESSED & MOUSE_OVER state Reviewed-by: tr, aivanov --- .../SynthButtonUI/6276188/bug6276188.java | 51 +++++++++++++------ 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/test/jdk/javax/swing/plaf/synth/SynthButtonUI/6276188/bug6276188.java b/test/jdk/javax/swing/plaf/synth/SynthButtonUI/6276188/bug6276188.java index be9c9457fff..9b689d2fe2c 100644 --- a/test/jdk/javax/swing/plaf/synth/SynthButtonUI/6276188/bug6276188.java +++ b/test/jdk/javax/swing/plaf/synth/SynthButtonUI/6276188/bug6276188.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,40 +21,53 @@ * questions. */ /** - * @test 1.4 08/08/05 + * @test * @key headful * @bug 6276188 * @library ../../../../regtesthelpers * @build Util - * @author Romain Guy * @summary Tests PRESSED and MOUSE_OVER and FOCUSED state for buttons with Synth. * @run main/othervm -Dsun.java2d.uiScale=1 bug6276188 */ -import java.awt.*; -import java.awt.image.*; -import java.awt.event.*; -import javax.swing.*; -import javax.swing.plaf.synth.*; +import java.io.File; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.image.BufferedImage; +import java.awt.event.InputEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import javax.imageio.ImageIO; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.plaf.synth.SynthLookAndFeel; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import java.util.concurrent.CountDownLatch; public class bug6276188 { private static JButton button; - private static Point p; private static JFrame testFrame; // move away from cursor - private final static int OFFSET_X = -20; - private final static int OFFSET_Y = -20; + private final static int OFFSET_X = 20; + private final static int OFFSET_Y = 20; public static void main(String[] args) throws Throwable { + Robot robot = new Robot(); try { - Robot robot = new Robot(); robot.setAutoDelay(100); SynthLookAndFeel lookAndFeel = new SynthLookAndFeel(); lookAndFeel.load(bug6276188.class.getResourceAsStream("bug6276188.xml"), bug6276188.class); UIManager.setLookAndFeel(lookAndFeel); + CountDownLatch latch = new CountDownLatch(1); SwingUtilities.invokeAndWait(new Runnable() { public void run() { @@ -62,6 +75,13 @@ public class bug6276188 { testFrame.setLayout(new BorderLayout()); testFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); testFrame.add(BorderLayout.CENTER, button = new JButton()); + button.addMouseListener(new MouseAdapter() { + @Override + public void mousePressed(MouseEvent e) { + System.out.println("Mouse pressed"); + latch.countDown(); + } + }); testFrame.setSize(new Dimension(320, 200)); testFrame.setLocationRelativeTo(null); @@ -72,13 +92,14 @@ public class bug6276188 { robot.waitForIdle(); robot.delay(1000); - p = Util.getCenterPoint(button); + Point p = Util.getCenterPoint(button); System.out.println("Button center point: " + p); robot.mouseMove(p.x , p.y); robot.waitForIdle(); robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); - robot.waitForIdle(); + latch.await(); + robot.delay(1000); Color color = robot.getPixelColor(p.x - OFFSET_X, p.y - OFFSET_Y); robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); @@ -89,7 +110,7 @@ public class bug6276188 { Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); Rectangle screen = new Rectangle(0, 0, (int) screenSize.getWidth(), (int) screenSize.getHeight()); BufferedImage img = robot.createScreenCapture(screen); - javax.imageio.ImageIO.write(img, "png", new java.io.File("image.png")); + ImageIO.write(img, "png", new File("image.png")); throw new RuntimeException("Synth ButtonUI does not handle PRESSED & MOUSE_OVER state"); } } finally { From 07549f3e1539a2dd491a4f9ffe9df8580d7d7dea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Maillard?= Date: Tue, 7 Oct 2025 07:43:43 +0000 Subject: [PATCH 0080/1639] 8360389: Support printing from C2 compiled code Reviewed-by: kvn, thartmann, mhaessig --- src/hotspot/share/opto/compile.cpp | 155 ++++++++++++++++++++ src/hotspot/share/opto/compile.hpp | 22 +++ src/hotspot/share/opto/runtime.cpp | 56 +++++++ src/hotspot/share/opto/runtime.hpp | 10 ++ src/hotspot/share/runtime/sharedRuntime.cpp | 40 +++++ src/hotspot/share/runtime/sharedRuntime.hpp | 34 +++++ 6 files changed, 317 insertions(+) diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index 7f63efe9e5e..6babc13e1b3 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -5378,3 +5378,158 @@ Node* Compile::narrow_value(BasicType bt, Node* value, const Type* type, PhaseGV void Compile::record_method_not_compilable_oom() { record_method_not_compilable(CompilationMemoryStatistic::failure_reason_memlimit()); } + +#ifndef PRODUCT +// Collects all the control inputs from nodes on the worklist and from their data dependencies +static void find_candidate_control_inputs(Unique_Node_List& worklist, Unique_Node_List& candidates) { + // Follow non-control edges until we reach CFG nodes + for (uint i = 0; i < worklist.size(); i++) { + const Node* n = worklist.at(i); + for (uint j = 0; j < n->req(); j++) { + Node* in = n->in(j); + if (in == nullptr || in->is_Root()) { + continue; + } + if (in->is_CFG()) { + if (in->is_Call()) { + // The return value of a call is only available if the call did not result in an exception + Node* control_proj_use = in->as_Call()->proj_out(TypeFunc::Control)->unique_out(); + if (control_proj_use->is_Catch()) { + Node* fall_through = control_proj_use->as_Catch()->proj_out(CatchProjNode::fall_through_index); + candidates.push(fall_through); + continue; + } + } + + if (in->is_Multi()) { + // We got here by following data inputs so we should only have one control use + // (no IfNode, etc) + assert(!n->is_MultiBranch(), "unexpected node type: %s", n->Name()); + candidates.push(in->as_Multi()->proj_out(TypeFunc::Control)); + } else { + candidates.push(in); + } + } else { + worklist.push(in); + } + } + } +} + +// Returns the candidate node that is a descendant to all the other candidates +static Node* pick_control(Unique_Node_List& candidates) { + Unique_Node_List worklist; + worklist.copy(candidates); + + // Traverse backwards through the CFG + for (uint i = 0; i < worklist.size(); i++) { + const Node* n = worklist.at(i); + if (n->is_Root()) { + continue; + } + for (uint j = 0; j < n->req(); j++) { + // Skip backedge of loops to avoid cycles + if (n->is_Loop() && j == LoopNode::LoopBackControl) { + continue; + } + + Node* pred = n->in(j); + if (pred != nullptr && pred != n && pred->is_CFG()) { + worklist.push(pred); + // if pred is an ancestor of n, then pred is an ancestor to at least one candidate + candidates.remove(pred); + } + } + } + + assert(candidates.size() == 1, "unexpected control flow"); + return candidates.at(0); +} + +// Initialize a parameter input for a debug print call, using a placeholder for jlong and jdouble +static void debug_print_init_parm(Node* call, Node* parm, Node* half, int* pos) { + call->init_req((*pos)++, parm); + const BasicType bt = parm->bottom_type()->basic_type(); + if (bt == T_LONG || bt == T_DOUBLE) { + call->init_req((*pos)++, half); + } +} + +Node* Compile::make_debug_print_call(const char* str, address call_addr, PhaseGVN* gvn, + Node* parm0, Node* parm1, + Node* parm2, Node* parm3, + Node* parm4, Node* parm5, + Node* parm6) const { + Node* str_node = gvn->transform(new ConPNode(TypeRawPtr::make(((address) str)))); + const TypeFunc* type = OptoRuntime::debug_print_Type(parm0, parm1, parm2, parm3, parm4, parm5, parm6); + Node* call = new CallLeafNode(type, call_addr, "debug_print", TypeRawPtr::BOTTOM); + + // find the most suitable control input + Unique_Node_List worklist, candidates; + if (parm0 != nullptr) { worklist.push(parm0); + if (parm1 != nullptr) { worklist.push(parm1); + if (parm2 != nullptr) { worklist.push(parm2); + if (parm3 != nullptr) { worklist.push(parm3); + if (parm4 != nullptr) { worklist.push(parm4); + if (parm5 != nullptr) { worklist.push(parm5); + if (parm6 != nullptr) { worklist.push(parm6); + /* close each nested if ===> */ } } } } } } } + find_candidate_control_inputs(worklist, candidates); + Node* control = nullptr; + if (candidates.size() == 0) { + control = C->start()->proj_out(TypeFunc::Control); + } else { + control = pick_control(candidates); + } + + // find all the previous users of the control we picked + GrowableArray users_of_control; + for (DUIterator_Fast kmax, i = control->fast_outs(kmax); i < kmax; i++) { + Node* use = control->fast_out(i); + if (use->is_CFG() && use != control) { + users_of_control.push(use); + } + } + + // we do not actually care about IO and memory as it uses neither + call->init_req(TypeFunc::Control, control); + call->init_req(TypeFunc::I_O, top()); + call->init_req(TypeFunc::Memory, top()); + call->init_req(TypeFunc::FramePtr, C->start()->proj_out(TypeFunc::FramePtr)); + call->init_req(TypeFunc::ReturnAdr, top()); + + int pos = TypeFunc::Parms; + call->init_req(pos++, str_node); + if (parm0 != nullptr) { debug_print_init_parm(call, parm0, top(), &pos); + if (parm1 != nullptr) { debug_print_init_parm(call, parm1, top(), &pos); + if (parm2 != nullptr) { debug_print_init_parm(call, parm2, top(), &pos); + if (parm3 != nullptr) { debug_print_init_parm(call, parm3, top(), &pos); + if (parm4 != nullptr) { debug_print_init_parm(call, parm4, top(), &pos); + if (parm5 != nullptr) { debug_print_init_parm(call, parm5, top(), &pos); + if (parm6 != nullptr) { debug_print_init_parm(call, parm6, top(), &pos); + /* close each nested if ===> */ } } } } } } } + assert(call->in(call->req()-1) != nullptr, "must initialize all parms"); + + call = gvn->transform(call); + Node* call_control_proj = gvn->transform(new ProjNode(call, TypeFunc::Control)); + + // rewire previous users to have the new call as control instead + PhaseIterGVN* igvn = gvn->is_IterGVN(); + for (int i = 0; i < users_of_control.length(); i++) { + Node* use = users_of_control.at(i); + for (uint j = 0; j < use->req(); j++) { + if (use->in(j) == control) { + if (igvn != nullptr) { + igvn->replace_input_of(use, j, call_control_proj); + } else { + gvn->hash_delete(use); + use->set_req(j, call_control_proj); + gvn->hash_insert(use); + } + } + } + } + + return call; +} +#endif // !PRODUCT diff --git a/src/hotspot/share/opto/compile.hpp b/src/hotspot/share/opto/compile.hpp index a68da644d82..66a5497a7ad 100644 --- a/src/hotspot/share/opto/compile.hpp +++ b/src/hotspot/share/opto/compile.hpp @@ -1316,6 +1316,28 @@ public: BasicType out_bt, BasicType in_bt); static Node* narrow_value(BasicType bt, Node* value, const Type* type, PhaseGVN* phase, bool transform_res); + +#ifndef PRODUCT +private: + // getting rid of the template makes things easier + Node* make_debug_print_call(const char* str, address call_addr, PhaseGVN* gvn, + Node* parm0 = nullptr, Node* parm1 = nullptr, + Node* parm2 = nullptr, Node* parm3 = nullptr, + Node* parm4 = nullptr, Node* parm5 = nullptr, + Node* parm6 = nullptr) const; + +public: + // Creates a CallLeafNode for a runtime call that prints a static string and the values of the + // nodes passed as arguments. + // This function also takes care of doing the necessary wiring, including finding a suitable control + // based on the nodes that need to be printed. Note that passing nodes that have incompatible controls + // is undefined behavior. + template + Node* make_debug_print(const char* str, PhaseGVN* gvn, NN... in) { + address call_addr = CAST_FROM_FN_PTR(address, SharedRuntime::debug_print); + return make_debug_print_call(str, call_addr, gvn, in...); + } +#endif }; #endif // SHARE_OPTO_COMPILE_HPP diff --git a/src/hotspot/share/opto/runtime.cpp b/src/hotspot/share/opto/runtime.cpp index 072b1384921..9de9fe5da03 100644 --- a/src/hotspot/share/opto/runtime.cpp +++ b/src/hotspot/share/opto/runtime.cpp @@ -1780,6 +1780,62 @@ static const TypeFunc* make_osr_end_Type() { return TypeFunc::make(domain, range); } +#ifndef PRODUCT +static void debug_print_convert_type(const Type** fields, int* argp, Node *parm) { + const BasicType bt = parm->bottom_type()->basic_type(); + fields[(*argp)++] = Type::get_const_basic_type(bt); + if (bt == T_LONG || bt == T_DOUBLE) { + fields[(*argp)++] = Type::HALF; + } +} + +static void update_arg_cnt(const Node* parm, int* arg_cnt) { + (*arg_cnt)++; + const BasicType bt = parm->bottom_type()->basic_type(); + if (bt == T_LONG || bt == T_DOUBLE) { + (*arg_cnt)++; + } +} + +const TypeFunc* OptoRuntime::debug_print_Type(Node* parm0, Node* parm1, + Node* parm2, Node* parm3, + Node* parm4, Node* parm5, + Node* parm6) { + int argcnt = 1; + if (parm0 != nullptr) { update_arg_cnt(parm0, &argcnt); + if (parm1 != nullptr) { update_arg_cnt(parm1, &argcnt); + if (parm2 != nullptr) { update_arg_cnt(parm2, &argcnt); + if (parm3 != nullptr) { update_arg_cnt(parm3, &argcnt); + if (parm4 != nullptr) { update_arg_cnt(parm4, &argcnt); + if (parm5 != nullptr) { update_arg_cnt(parm5, &argcnt); + if (parm6 != nullptr) { update_arg_cnt(parm6, &argcnt); + /* close each nested if ===> */ } } } } } } } + + // create input type (domain) + const Type** fields = TypeTuple::fields(argcnt); + int argp = TypeFunc::Parms; + fields[argp++] = TypePtr::NOTNULL; // static string pointer + + if (parm0 != nullptr) { debug_print_convert_type(fields, &argp, parm0); + if (parm1 != nullptr) { debug_print_convert_type(fields, &argp, parm1); + if (parm2 != nullptr) { debug_print_convert_type(fields, &argp, parm2); + if (parm3 != nullptr) { debug_print_convert_type(fields, &argp, parm3); + if (parm4 != nullptr) { debug_print_convert_type(fields, &argp, parm4); + if (parm5 != nullptr) { debug_print_convert_type(fields, &argp, parm5); + if (parm6 != nullptr) { debug_print_convert_type(fields, &argp, parm6); + /* close each nested if ===> */ } } } } } } } + + assert(argp == TypeFunc::Parms+argcnt, "correct decoding"); + const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields); + + // no result type needed + fields = TypeTuple::fields(1); + fields[TypeFunc::Parms+0] = nullptr; // void + const TypeTuple* range = TypeTuple::make(TypeFunc::Parms, fields); + return TypeFunc::make(domain, range); +} +#endif // PRODUCT + //------------------------------------------------------------------------------------- // register policy diff --git a/src/hotspot/share/opto/runtime.hpp b/src/hotspot/share/opto/runtime.hpp index 40e436c0d5c..76e69fd9d36 100644 --- a/src/hotspot/share/opto/runtime.hpp +++ b/src/hotspot/share/opto/runtime.hpp @@ -737,6 +737,16 @@ private: return _dtrace_object_alloc_Type; } +#ifndef PRODUCT + // Signature for runtime calls in debug printing nodes, which depends on which nodes are actually passed + // Note: we do not allow more than 7 node arguments as GraphKit::make_runtime_call only allows 8, and we need + // one for the static string + static const TypeFunc* debug_print_Type(Node* parm0 = nullptr, Node* parm1 = nullptr, + Node* parm2 = nullptr, Node* parm3 = nullptr, + Node* parm4 = nullptr, Node* parm5 = nullptr, + Node* parm6 = nullptr); +#endif // PRODUCT + private: static NamedCounter * volatile _named_counters; diff --git a/src/hotspot/share/runtime/sharedRuntime.cpp b/src/hotspot/share/runtime/sharedRuntime.cpp index 85aeba361ff..a8c9a64d63a 100644 --- a/src/hotspot/share/runtime/sharedRuntime.cpp +++ b/src/hotspot/share/runtime/sharedRuntime.cpp @@ -264,6 +264,46 @@ void SharedRuntime::print_ic_miss_histogram() { tty->print_cr("Total IC misses: %7d", tot_misses); } } + +#ifdef COMPILER2 +// Runtime methods for printf-style debug nodes (same printing format as fieldDescriptor::print_on_for) +void SharedRuntime::debug_print_value(jboolean x) { + tty->print_cr("boolean %d", x); +} + +void SharedRuntime::debug_print_value(jbyte x) { + tty->print_cr("byte %d", x); +} + +void SharedRuntime::debug_print_value(jshort x) { + tty->print_cr("short %d", x); +} + +void SharedRuntime::debug_print_value(jchar x) { + tty->print_cr("char %c %d", isprint(x) ? x : ' ', x); +} + +void SharedRuntime::debug_print_value(jint x) { + tty->print_cr("int %d", x); +} + +void SharedRuntime::debug_print_value(jlong x) { + tty->print_cr("long " JLONG_FORMAT, x); +} + +void SharedRuntime::debug_print_value(jfloat x) { + tty->print_cr("float %f", x); +} + +void SharedRuntime::debug_print_value(jdouble x) { + tty->print_cr("double %lf", x); +} + +void SharedRuntime::debug_print_value(oopDesc* x) { + x->print(); +} +#endif // COMPILER2 + #endif // PRODUCT diff --git a/src/hotspot/share/runtime/sharedRuntime.hpp b/src/hotspot/share/runtime/sharedRuntime.hpp index 2a19b80c3b5..93cd92b3a32 100644 --- a/src/hotspot/share/runtime/sharedRuntime.hpp +++ b/src/hotspot/share/runtime/sharedRuntime.hpp @@ -32,6 +32,7 @@ #include "memory/allStatic.hpp" #include "memory/metaspaceClosure.hpp" #include "memory/resourceArea.hpp" +#include "runtime/safepointVerifiers.hpp" #include "runtime/stubInfo.hpp" #include "utilities/macros.hpp" @@ -635,6 +636,39 @@ class SharedRuntime: AllStatic { static void print_call_statistics(uint64_t comp_total); static void print_ic_miss_histogram(); +#ifdef COMPILER2 + // Runtime methods for printf-style debug nodes + static void debug_print_value(jboolean x); + static void debug_print_value(jbyte x); + static void debug_print_value(jshort x); + static void debug_print_value(jchar x); + static void debug_print_value(jint x); + static void debug_print_value(jlong x); + static void debug_print_value(jfloat x); + static void debug_print_value(jdouble x); + static void debug_print_value(oopDesc* x); + + template + static void debug_print_rec(T arg, Rest... args) { + debug_print_value(arg); + debug_print_rec(args...); + } + + static void debug_print_rec() {} + + // template is required here as we need to know the exact signature at compile-time + template + static void debug_print(const char *str, TT... args) { + // these three lines are the manual expansion of JRT_LEAF ... JRT_END, does not work well with templates + DEBUG_ONLY(NoHandleMark __hm;) + os::verify_stack_alignment(); + DEBUG_ONLY(NoSafepointVerifier __nsv;) + + tty->print_cr("%s", str); + debug_print_rec(args...); + } +#endif // COMPILER2 + #endif // PRODUCT static void print_statistics() PRODUCT_RETURN; From c06d6805aae3af2e6175f3f43deea46c9ce08bc6 Mon Sep 17 00:00:00 2001 From: Daniel Skantz Date: Tue, 7 Oct 2025 09:04:39 +0000 Subject: [PATCH 0081/1639] 8362394: C2: Repeated stacked string concatenation fails with "Hit MemLimit" and other resourcing errors Reviewed-by: chagedorn, rcastanedalo --- src/hotspot/share/opto/stringopts.cpp | 22 ++++- .../stringopts/TestStackedConcatsMany.java | 95 +++++++++++++++++++ 2 files changed, 116 insertions(+), 1 deletion(-) create mode 100644 test/hotspot/jtreg/compiler/stringopts/TestStackedConcatsMany.java diff --git a/src/hotspot/share/opto/stringopts.cpp b/src/hotspot/share/opto/stringopts.cpp index 25aa82870c3..420423dd246 100644 --- a/src/hotspot/share/opto/stringopts.cpp +++ b/src/hotspot/share/opto/stringopts.cpp @@ -53,6 +53,11 @@ class StringConcat : public ResourceObj { Node_List _uncommon_traps; // Uncommon traps that needs to be rewritten // to restart at the initial JVMState. + static constexpr uint STACKED_CONCAT_UPPER_BOUND = 256; // argument limit for a merged concat. + // The value 256 was derived by measuring + // compilation time on variable length sequences + // of stackable concatenations and chosen to keep + // a safe margin to any critical point. public: // Mode for converting arguments to Strings enum { @@ -295,6 +300,8 @@ StringConcat* StringConcat::merge(StringConcat* other, Node* arg) { } assert(result->_control.contains(other->_end), "what?"); assert(result->_control.contains(_begin), "what?"); + + uint arguments_appended = 0; for (int x = 0; x < num_arguments(); x++) { Node* argx = argument_uncast(x); if (argx == arg) { @@ -303,8 +310,21 @@ StringConcat* StringConcat::merge(StringConcat* other, Node* arg) { for (int y = 0; y < other->num_arguments(); y++) { result->append(other->argument(y), other->mode(y)); } + arguments_appended += other->num_arguments(); } else { result->append(argx, mode(x)); + arguments_appended++; + } + // Check if this concatenation would result in an excessive number of arguments + // -- leading to high memory use, compilation time, and later, a large number of IR nodes + // -- and bail out in that case. + if (arguments_appended > STACKED_CONCAT_UPPER_BOUND) { +#ifndef PRODUCT + if (PrintOptimizeStringConcat) { + tty->print_cr("Merge candidate of length %d exceeds argument limit", arguments_appended); + } +#endif + return nullptr; } } result->set_allocation(other->_begin); @@ -680,7 +700,7 @@ PhaseStringOpts::PhaseStringOpts(PhaseGVN* gvn): #endif StringConcat* merged = sc->merge(other, arg); - if (merged->validate_control_flow() && merged->validate_mem_flow()) { + if (merged != nullptr && merged->validate_control_flow() && merged->validate_mem_flow()) { #ifndef PRODUCT AtomicAccess::inc(&_stropts_merged); if (PrintOptimizeStringConcat) { diff --git a/test/hotspot/jtreg/compiler/stringopts/TestStackedConcatsMany.java b/test/hotspot/jtreg/compiler/stringopts/TestStackedConcatsMany.java new file mode 100644 index 00000000000..dbc6e495594 --- /dev/null +++ b/test/hotspot/jtreg/compiler/stringopts/TestStackedConcatsMany.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8362394 + * @summary Test that repeated stacked string concatenations do not + * consume too many compilation resources. + * @requires vm.compiler2.enabled + * @library /test/lib / + * @run main/othervm -XX:-OptoScheduling compiler.stringopts.TestStackedConcatsMany + * @run main/othervm -XX:-TieredCompilation -Xcomp -XX:-OptoScheduling + * -XX:CompileOnly=compiler.stringopts.TestStackedConcatsMany::f + * compiler.stringopts.TestStackedConcatsMany + */ + +// The test uses -XX:-OptoScheduling to avoid the assert "too many D-U pinch points" on aarch64 (JDK-8328078). + +package compiler.stringopts; + +import jdk.test.lib.Asserts; + +public class TestStackedConcatsMany { + + public static void main (String... args) { + new StringBuilder(); // Trigger loading of the StringBuilder class. + String s = f(); + String z = "xy"; + for (int i = 0; i < 24; i++) { + z = z + z; + } + Asserts.assertEQ(s, z); + } + + static String f() { + String s = "xy"; + s = new StringBuilder().append(s).append(s).toString(); + s = new StringBuilder().append(s).append(s).toString(); + + s = new StringBuilder().append(s).append(s).toString(); + s = new StringBuilder().append(s).append(s).toString(); + + s = new StringBuilder().append(s).append(s).toString(); + s = new StringBuilder().append(s).append(s).toString(); + + s = new StringBuilder().append(s).append(s).toString(); + s = new StringBuilder().append(s).append(s).toString(); + + s = new StringBuilder().append(s).append(s).toString(); + s = new StringBuilder().append(s).append(s).toString(); + + s = new StringBuilder().append(s).append(s).toString(); + s = new StringBuilder().append(s).append(s).toString(); + + s = new StringBuilder().append(s).append(s).toString(); + s = new StringBuilder().append(s).append(s).toString(); + + s = new StringBuilder().append(s).append(s).toString(); + s = new StringBuilder().append(s).append(s).toString(); + + s = new StringBuilder().append(s).append(s).toString(); + s = new StringBuilder().append(s).append(s).toString(); + + s = new StringBuilder().append(s).append(s).toString(); + s = new StringBuilder().append(s).append(s).toString(); + + s = new StringBuilder().append(s).append(s).toString(); + s = new StringBuilder().append(s).append(s).toString(); + + s = new StringBuilder().append(s).append(s).toString(); + s = new StringBuilder().append(s).append(s).toString(); + + return s; + } +} From aed9485bbb1d93063e5e5f60ed84bfb36053bdd1 Mon Sep 17 00:00:00 2001 From: Andrew Haley Date: Tue, 7 Oct 2025 10:09:23 +0000 Subject: [PATCH 0082/1639] 8368303: AlwaysAtomicAccesses is excessively strict Reviewed-by: shade, vlivanov, dlong --- .../share/gc/shared/c1/barrierSetC1.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/hotspot/share/gc/shared/c1/barrierSetC1.cpp b/src/hotspot/share/gc/shared/c1/barrierSetC1.cpp index ac640fb88d2..a31078f7e67 100644 --- a/src/hotspot/share/gc/shared/c1/barrierSetC1.cpp +++ b/src/hotspot/share/gc/shared/c1/barrierSetC1.cpp @@ -38,6 +38,16 @@ #define __ gen->lir()-> #endif +// Return true iff an access to bt is single-copy atomic. + +// The JMM requires atomicity for all accesses to fields of primitive +// types other than double and long. In practice, HotSpot assumes that +// on all processors, accesses to memory operands of wordSize and +// smaller are atomic. +static bool access_is_atomic(BasicType bt) { + return type2aelembytes(bt) <= wordSize; +} + LIR_Opr BarrierSetC1::resolve_address(LIRAccess& access, bool resolve_in_register) { DecoratorSet decorators = access.decorators(); bool is_array = (decorators & IS_ARRAY) != 0; @@ -140,7 +150,7 @@ LIR_Opr BarrierSetC1::atomic_add_at(LIRAccess& access, LIRItem& value) { void BarrierSetC1::store_at_resolved(LIRAccess& access, LIR_Opr value) { DecoratorSet decorators = access.decorators(); bool is_volatile = (decorators & MO_SEQ_CST) != 0; - bool is_atomic = is_volatile || AlwaysAtomicAccesses; + bool needs_atomic = AlwaysAtomicAccesses && !access_is_atomic(value->type()); bool needs_patching = (decorators & C1_NEEDS_PATCHING) != 0; bool mask_boolean = (decorators & C1_MASK_BOOLEAN) != 0; LIRGenerator* gen = access.gen(); @@ -154,7 +164,7 @@ void BarrierSetC1::store_at_resolved(LIRAccess& access, LIR_Opr value) { } LIR_PatchCode patch_code = needs_patching ? lir_patch_normal : lir_patch_none; - if (is_atomic && !needs_patching) { + if ((is_volatile || needs_atomic) && !needs_patching) { gen->volatile_field_store(value, access.resolved_addr()->as_address_ptr(), access.access_emit_info()); } else { __ store(value, access.resolved_addr()->as_address_ptr(), access.access_emit_info(), patch_code); @@ -169,7 +179,7 @@ void BarrierSetC1::load_at_resolved(LIRAccess& access, LIR_Opr result) { LIRGenerator *gen = access.gen(); DecoratorSet decorators = access.decorators(); bool is_volatile = (decorators & MO_SEQ_CST) != 0; - bool is_atomic = is_volatile || AlwaysAtomicAccesses; + bool needs_atomic = AlwaysAtomicAccesses && !access_is_atomic(result->type()); bool needs_patching = (decorators & C1_NEEDS_PATCHING) != 0; bool mask_boolean = (decorators & C1_MASK_BOOLEAN) != 0; bool in_native = (decorators & IN_NATIVE) != 0; @@ -181,7 +191,7 @@ void BarrierSetC1::load_at_resolved(LIRAccess& access, LIR_Opr result) { LIR_PatchCode patch_code = needs_patching ? lir_patch_normal : lir_patch_none; if (in_native) { __ move_wide(access.resolved_addr()->as_address_ptr(), result); - } else if (is_atomic && !needs_patching) { + } else if ((is_volatile || needs_atomic) && !needs_patching) { gen->volatile_field_load(access.resolved_addr()->as_address_ptr(), result, access.access_emit_info()); } else { __ load(access.resolved_addr()->as_address_ptr(), result, access.access_emit_info(), patch_code); From 6bec42adcc1d99e16ddd5148bb4012c74a0c3090 Mon Sep 17 00:00:00 2001 From: Alexey Ivanov Date: Tue, 7 Oct 2025 10:21:33 +0000 Subject: [PATCH 0083/1639] 8368892: Make JEditorPane/TestBrowserBGColor.java headless Reviewed-by: serb, azvegint --- .../swing/JEditorPane/TestBrowserBGColor.java | 139 ++++++++---------- 1 file changed, 62 insertions(+), 77 deletions(-) diff --git a/test/jdk/javax/swing/JEditorPane/TestBrowserBGColor.java b/test/jdk/javax/swing/JEditorPane/TestBrowserBGColor.java index bff0f7c4aaa..9abe286a75d 100644 --- a/test/jdk/javax/swing/JEditorPane/TestBrowserBGColor.java +++ b/test/jdk/javax/swing/JEditorPane/TestBrowserBGColor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,94 +23,79 @@ /* * @test - * @key headful * @bug 8213781 * @summary Verify webpage background color renders correctly in JEditorPane */ -import java.awt.Toolkit; -import java.awt.event.WindowAdapter; -import java.awt.event.WindowEvent; -import java.io.IOException; -import java.net.MalformedURLException; -import javax.swing.JDialog; -import javax.swing.JEditorPane; -import javax.swing.JFrame; -import javax.swing.JScrollPane; -import javax.swing.SwingUtilities; -import javax.swing.event.HyperlinkEvent; -import javax.swing.event.HyperlinkListener; -import javax.swing.text.html.HTMLFrameHyperlinkEvent; -import javax.swing.text.html.HTMLDocument; import java.awt.Color; -import java.awt.Insets; -import java.awt.Point; -import java.awt.Robot; +import java.awt.Graphics; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.util.Objects; +import java.util.stream.IntStream; -public class TestBrowserBGColor extends JFrame implements HyperlinkListener { +import javax.imageio.ImageIO; +import javax.swing.JEditorPane; +import javax.swing.text.StyleConstants; +import javax.swing.text.View; - private static TestBrowserBGColor b; - private static JEditorPane browser; +import static java.awt.image.BufferedImage.TYPE_INT_RGB; +import static java.lang.Integer.toHexString; + +public final class TestBrowserBGColor { + + private static final String HTML_DOC = + "" + + "" + + "" + + "Title" + + " "; + + private static final int SIZE = 300; public static void main(final String[] args) throws Exception { - Robot r = new Robot(); - SwingUtilities.invokeAndWait(() -> { - try { - b = new TestBrowserBGColor(); - } catch (Exception e) { - throw new RuntimeException(e); - } - b.setSize(Toolkit.getDefaultToolkit().getScreenSize()); - b.setVisible(true); - b.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); - b.addWindowListener(new WindowAdapter() { - public void windowClosing(WindowEvent e) { - b.dispose(); - b = null; - } - }); - }); - - r.waitForIdle(); - r.delay(500); - - SwingUtilities.invokeAndWait(() -> { - Insets insets = browser.getInsets(); - Point loc = browser.getLocationOnScreen(); - Color c = r.getPixelColor( loc.x + insets.left+100, - loc.y + insets.top + 100); - b.dispose(); - if (!c.equals(Color.WHITE)) { - throw new RuntimeException("webpage background color wrong"); - } - }); - } - - - String htmlDoc = " Title "; - - public TestBrowserBGColor() throws IOException, MalformedURLException { - browser = new JEditorPane("text/html", htmlDoc); + JEditorPane browser = new JEditorPane("text/html", HTML_DOC); browser.setEditable(false); - browser.addHyperlinkListener(this); - JScrollPane scroll = new JScrollPane(browser); - getContentPane().add(scroll); + browser.setSize(SIZE, SIZE); + + BufferedImage image = new BufferedImage(SIZE, SIZE, TYPE_INT_RGB); + Graphics g = image.getGraphics(); + browser.paint(g); + g.dispose(); + + Color bgColor = StyleConstants.getBackground( + getBodyView(browser.getUI() + .getRootView(browser)) + .getAttributes()); + if (!bgColor.equals(Color.WHITE)) { + saveImage(image); + throw new RuntimeException("Wrong background color: " + + toHexString(bgColor.getRGB()) + + " vs " + + toHexString(Color.WHITE.getRGB())); + } } - public void hyperlinkUpdate(final HyperlinkEvent e) { - if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { - JEditorPane pane = (JEditorPane) e.getSource(); - if (e instanceof HTMLFrameHyperlinkEvent) { - HTMLFrameHyperlinkEvent evt = (HTMLFrameHyperlinkEvent) e; - HTMLDocument doc = (HTMLDocument) pane.getDocument(); - doc.processHTMLFrameHyperlinkEvent(evt); - } else { - try { - pane.setPage(e.getURL()); - } catch (Throwable t) { - t.printStackTrace(); - } - } + private static View getBodyView(final View view) { + if ("body".equals(view.getElement() + .getName())) { + return view; + } + + return IntStream.range(0, view.getViewCount()) + .mapToObj(view::getView) + .map(TestBrowserBGColor::getBodyView) + .filter(Objects::nonNull) + .findFirst() + .orElse(null); + } + + private static void saveImage(BufferedImage image) { + try { + ImageIO.write(image, "png", + new File("html-rendering.png")); + } catch (IOException ignored) { } } } From 9c46febcac01b9f1831f5f3e2a68dd1f1612a01f Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Tue, 7 Oct 2025 12:47:40 +0000 Subject: [PATCH 0084/1639] 8245234: Still seeing missing mixed stack traces, even after JDK-8234624 Reviewed-by: kevinw, cjplummer --- .../linux/amd64/LinuxAMD64CFrame.java | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/amd64/LinuxAMD64CFrame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/amd64/LinuxAMD64CFrame.java index 5f3c9786d6e..3dfb83c9f5a 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/amd64/LinuxAMD64CFrame.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/debugger/linux/amd64/LinuxAMD64CFrame.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -145,17 +145,12 @@ public final class LinuxAMD64CFrame extends BasicCFrame { } DwarfParser nextDwarf = null; - - if ((dwarf != null) && dwarf.isIn(nextPC)) { - nextDwarf = dwarf; - } else { - Address libptr = dbg.findLibPtrByAddress(nextPC); - if (libptr != null) { - try { - nextDwarf = new DwarfParser(libptr); - } catch (DebuggerException e) { - // Bail out to Java frame - } + Address libptr = dbg.findLibPtrByAddress(nextPC); + if (libptr != null) { + try { + nextDwarf = new DwarfParser(libptr); + } catch (DebuggerException e) { + // Bail out to Java frame } } From 4b4d0cd35a32448e4b056109c502af2765766432 Mon Sep 17 00:00:00 2001 From: Johny Jose Date: Tue, 7 Oct 2025 13:13:42 +0000 Subject: [PATCH 0085/1639] 8365398: TEST_BUG: java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java failing intermittently Reviewed-by: msheppar, smarks, jpai --- test/jdk/ProblemList.txt | 1 - .../checkLeaseInfoLeak/CheckLeaseLeak.java | 25 ++++++++++++++----- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 8d13670805f..48a495bc238 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -608,7 +608,6 @@ java/rmi/transport/rapidExportUnexport/RapidExportUnexport.java 7146541 linux-al java/rmi/registry/readTest/CodebaseTest.java 8173324 windows-all java/rmi/registry/multipleRegistries/MultipleRegistries.java 8268182 macosx-all -java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java 8365398 generic-all java/rmi/Naming/DefaultRegistryPort.java 8005619 windows-all java/rmi/Naming/legalRegistryNames/LegalRegistryNames.java 8005619 windows-all diff --git a/test/jdk/java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java b/test/jdk/java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java index 4de6598a0f4..f40502601d2 100644 --- a/test/jdk/java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java +++ b/test/jdk/java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java @@ -59,10 +59,13 @@ import java.io.*; import java.lang.reflect.*; import java.rmi.registry.*; import sun.rmi.transport.*; +import java.util.concurrent.CountDownLatch; public class CheckLeaseLeak extends UnicastRemoteObject implements LeaseLeak { public CheckLeaseLeak() throws RemoteException { } - public void ping () throws RemoteException { } + public void ping () throws RemoteException { + remoteCallsComplete.countDown(); + } /** * Id to fake the DGC_ID, so we can later get a reference to the @@ -74,6 +77,9 @@ public class CheckLeaseLeak extends UnicastRemoteObject implements LeaseLeak { private final static int numberPingCalls = 0; private final static int CHECK_INTERVAL = 400; private final static int LEASE_VALUE = 20; + private static final int NO_OF_CLIENTS = ITERATIONS; + private static final int GOOD_LUCK_FACTOR = 2; + private static CountDownLatch remoteCallsComplete = new CountDownLatch(NO_OF_CLIENTS); public static void main (String[] args) { CheckLeaseLeak leakServer = null; @@ -113,8 +119,14 @@ public class CheckLeaseLeak extends UnicastRemoteObject implements LeaseLeak { jvm.destroy(); } } + try { + remoteCallsComplete.await(); + System.out.println("remoteCallsComplete . . . "); + } catch (InterruptedException intEx) { + System.out.println("remoteCallsComplete.await interrupted . . . "); + } + Thread.sleep(NO_OF_CLIENTS * LEASE_VALUE * GOOD_LUCK_FACTOR); numLeft = getDGCLeaseTableSize(); - Thread.sleep(3000); } catch(Exception e) { TestLibrary.bomb("CheckLeaseLeak Error: ", e); @@ -125,8 +137,8 @@ public class CheckLeaseLeak extends UnicastRemoteObject implements LeaseLeak { } } - /* numLeft should be 4 - if 11 there is a problem. */ - if (numLeft > 4) { + /* numLeft should not be greater than 2 - if 11 there is a problem. */ + if (numLeft > 2) { TestLibrary.bomb("Too many objects in DGCImpl.leaseTable: "+ numLeft); } else { @@ -204,8 +216,9 @@ public class CheckLeaseLeak extends UnicastRemoteObject implements LeaseLeak { * objects if the LeaseInfo memory leak is not fixed. */ leaseTable = (Map) f.get(dgcImpl[0]); - - numLeaseInfosLeft = leaseTable.size(); + synchronized (leaseTable) { + numLeaseInfosLeft = leaseTable.size(); + } } catch(Exception e) { TestLibrary.bomb(e); From a9c93f865bb5438420bc4df278d211ff3af9a0ad Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Tue, 7 Oct 2025 13:40:19 +0000 Subject: [PATCH 0086/1639] 8369263: Parallel: Inline PSPromotionManager::push_depth Reviewed-by: iwalulya, shade, fandreuzzi --- src/hotspot/share/gc/parallel/psPromotionManager.hpp | 2 -- src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp | 6 +----- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/src/hotspot/share/gc/parallel/psPromotionManager.hpp b/src/hotspot/share/gc/parallel/psPromotionManager.hpp index 7d3a1682519..9808a55335d 100644 --- a/src/hotspot/share/gc/parallel/psPromotionManager.hpp +++ b/src/hotspot/share/gc/parallel/psPromotionManager.hpp @@ -102,8 +102,6 @@ class PSPromotionManager { void process_array_chunk(PartialArrayState* state, bool stolen); void push_objArray(oop old_obj, oop new_obj); - void push_depth(ScannerTask task); - inline void promotion_trace_event(oop new_obj, Klass* klass, size_t obj_size, uint age, bool tenured, const PSPromotionLAB* lab); diff --git a/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp b/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp index 4c12a4c357f..fb58c22cf29 100644 --- a/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp +++ b/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp @@ -50,10 +50,6 @@ inline PSPromotionManager* PSPromotionManager::manager_array(uint index) { return &_manager_array[index]; } -inline void PSPromotionManager::push_depth(ScannerTask task) { - claimed_stack_depth()->push(task); -} - template inline void PSPromotionManager::claim_or_forward_depth(T* p) { assert(ParallelScavengeHeap::heap()->is_in(p), "pointer outside heap"); @@ -62,7 +58,7 @@ inline void PSPromotionManager::claim_or_forward_depth(T* p) { oop obj = CompressedOops::decode_not_null(heap_oop); assert(!PSScavenge::is_obj_in_to_space(obj), "revisiting object?"); Prefetch::write(obj->base_addr(), oopDesc::mark_offset_in_bytes()); - push_depth(ScannerTask(p)); + claimed_stack_depth()->push(ScannerTask(p)); } } From 0f2a95c15d7c1e3796660d786c9a72497dab5ab1 Mon Sep 17 00:00:00 2001 From: jonghoonpark Date: Tue, 7 Oct 2025 15:13:23 +0000 Subject: [PATCH 0087/1639] 8365782: Remove unnecessary inclusion of in jfrOSInterface.cpp Reviewed-by: ayang, tschatzl --- src/hotspot/share/jfr/periodic/jfrOSInterface.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/hotspot/share/jfr/periodic/jfrOSInterface.cpp b/src/hotspot/share/jfr/periodic/jfrOSInterface.cpp index 2d4b99d59ab..18b2d7c5785 100644 --- a/src/hotspot/share/jfr/periodic/jfrOSInterface.cpp +++ b/src/hotspot/share/jfr/periodic/jfrOSInterface.cpp @@ -32,8 +32,6 @@ #include "runtime/vm_version.hpp" #include "utilities/ostream.hpp" -#include // for environment variables - static JfrOSInterface* _instance = nullptr; JfrOSInterface& JfrOSInterface::instance() { @@ -81,10 +79,7 @@ class JfrOSInterface::JfrOSInterfaceImpl : public JfrCHeapObj { // os information int os_version(char** os_version) const; - // environment information - void generate_environment_variables_events(); - - // system processes information + // system processes information int system_processes(SystemProcess** system_processes, int* no_of_sys_processes); int network_utilization(NetworkInterface** network_interfaces); From 8a20656ed03aa26806c7b4a4e361999dea62aa79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Walln=C3=B6fer?= Date: Tue, 7 Oct 2025 15:16:08 +0000 Subject: [PATCH 0088/1639] 8367321: Fix CSS bugs in dark theme 8366942: Dark mode pages briefly blink before going dark Reviewed-by: nbenalla, liach --- .../doclets/formats/html/markup/Head.java | 3 +- .../formats/html/resources/script.js.template | 60 +++++++++++-------- .../formats/html/resources/stylesheet.css | 58 +++++++++--------- .../javadoc/doclet/testSearch/TestSearch.java | 3 +- 4 files changed, 69 insertions(+), 55 deletions(-) diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java index 2b6bfa77951..cda4bc9a5be 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Head.java @@ -378,7 +378,8 @@ public class Head extends Content { mainBodyScript.append("const pathtoroot = ") .appendStringLiteral(ptrPath + "/") .append(";\n") - .append("loadScripts(document, 'script');"); + .append("loadScripts();\n") + .append("initTheme();\n"); } addScriptElement(head, DocPaths.JQUERY_JS); addScriptElement(head, DocPaths.JQUERY_UI_JS); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script.js.template b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script.js.template index b275323b2f5..b91f99b2c42 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script.js.template +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script.js.template @@ -11,12 +11,13 @@ var typeSearchIndex; var memberSearchIndex; var tagSearchIndex; -var oddRowColor = "odd-row-color"; -var evenRowColor = "even-row-color"; -var sortAsc = "sort-asc"; -var sortDesc = "sort-desc"; -var tableTab = "table-tab"; -var activeTableTab = "active-table-tab"; +const oddRowColor = "odd-row-color"; +const evenRowColor = "even-row-color"; +const sortAsc = "sort-asc"; +const sortDesc = "sort-desc"; +const tableTab = "table-tab"; +const activeTableTab = "active-table-tab"; +const THEMES = Object.freeze(["theme-light", "theme-dark", "theme-os"]); const linkIcon = "##REPLACE:doclet.Link_icon##"; const linkToSection = "##REPLACE:doclet.Link_to_section##"; @@ -30,21 +31,20 @@ if (typeof hljs !== "undefined") { } } -function loadScripts(doc, tag) { - createElem(doc, tag, 'script-files/search.js'); - - createElem(doc, tag, 'module-search-index.js'); - createElem(doc, tag, 'package-search-index.js'); - createElem(doc, tag, 'type-search-index.js'); - createElem(doc, tag, 'member-search-index.js'); - createElem(doc, tag, 'tag-search-index.js'); +function loadScripts() { + createScript('script-files/search.js'); + createScript('module-search-index.js'); + createScript('package-search-index.js'); + createScript('type-search-index.js'); + createScript('member-search-index.js'); + createScript('tag-search-index.js'); } -function createElem(doc, tag, path) { - var script = doc.createElement(tag); - var scriptElement = doc.getElementsByTagName(tag)[0]; +function createScript(path) { + var script = document.createElement("script"); script.src = pathtoroot + path; - scriptElement.parentNode.insertBefore(script, scriptElement); + var firstScript = document.getElementsByTagName("script")[0]; + firstScript.parentNode.insertBefore(script, firstScript); } // Helper for making content containing release names comparable lexicographically @@ -312,21 +312,31 @@ function makeFilterWidget(sidebar, updateToc) { return sidebar; } +function getTheme() { + return localStorage.getItem('theme') || THEMES[0]; +} + +function initTheme() { + document.body.classList.add(getTheme()); +} + function setTopMargin() { // Dynamically set scroll margin to accomodate for draft header var headerHeight = Math.ceil(document.querySelector("header").offsetHeight); document.querySelector(":root") .style.setProperty("--nav-height", headerHeight + "px"); } + document.addEventListener("readystatechange", (e) => { if (document.readyState === "interactive") { setTopMargin(); - } - if (sessionStorage.getItem("sidebar") === "hidden") { - const sidebar = document.querySelector(".main-grid nav.toc"); - if (sidebar) sidebar.classList.add("hide-sidebar"); + if (sessionStorage.getItem("sidebar") === "hidden") { + const sidebar = document.querySelector(".main-grid nav.toc"); + if (sidebar) sidebar.classList.add("hide-sidebar"); + } } }); + document.addEventListener("DOMContentLoaded", function(e) { setTopMargin(); const subnav = document.querySelector("ol.sub-nav-list"); @@ -375,13 +385,16 @@ document.addEventListener("DOMContentLoaded", function(e) { themePanelVisible = false; } } + var currentTheme = getTheme(); themePanel.querySelectorAll("input").forEach(input => { input.removeAttribute("disabled"); + if (input.id === currentTheme) { + input.checked = true; + } input.addEventListener("change", e => { setTheme(e.target.value); }) }); - const THEMES = ["theme-light", "theme-dark", "theme-os"]; function setTheme(theme) { THEMES.forEach(t => { if (t !== theme) document.body.classList.remove(t); @@ -390,7 +403,6 @@ document.addEventListener("DOMContentLoaded", function(e) { localStorage.setItem("theme", theme); document.getElementById(theme).checked = true; } - setTheme(localStorage.getItem("theme") || THEMES[0]); makeFilterWidget(sidebar, updateToc); if (tocMenu) { navbar.appendChild(tocMenu); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css index d61283dc677..4bb0fad4306 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/stylesheet.css @@ -73,7 +73,7 @@ body { --selected-link-color: #4a698a; /* Background colors for generated tables */ --table-header-color: #ebeff4; - --even-row-color: #ffffff; + --even-row-color: #fdfdfe; --odd-row-color: #f0f0f2; /* Text color for page title */ --title-color: #2c4557; @@ -109,17 +109,19 @@ body { /* Colors for invalid tag notifications */ --invalid-tag-background-color: #ffe6e6; --invalid-tag-text-color: #000000; + --icon-filter: none; + --caption-link-color: var(--subnav-link-color); } body.theme-dark { --body-text-color: #e8e8e8; --block-text-color: #e8e8e8; - --body-background-color: #222528; + --body-background-color: #1f2124; --section-background-color: var(--body-background-color); --detail-background-color: var(--body-background-color); --code-background-color: #303940; --mark-background-color: #313131; - --detail-block-color: #f4f4f4; + --detail-block-color: #31363c; --navbar-background-color: #395A6F; --navbar-text-color: #ffffff; --subnav-background-color: #3d454d; @@ -133,11 +135,11 @@ body.theme-dark { --odd-row-color: #2d3135; --title-color: #fff; --link-color: #94badb; - --link-color-active: #ffb45b; - --toc-background-color: #31363c; + --link-color-active: #e8a351; + --toc-background-color: #2f3439; --toc-highlight-color: var(--subnav-background-color); --toc-hover-color: #3f4146; - --snippet-background-color: #2d363c; + --snippet-background-color: #2c353b; --snippet-text-color: var(--block-text-color); --snippet-highlight-color: #f7c590; --pre-background-color: var(--snippet-background-color); @@ -155,10 +157,8 @@ body.theme-dark { --button-focus-filter: brightness(104%); --invalid-tag-background-color: #ffe6e6; --invalid-tag-text-color: #000000; - div.main-grid img, - .inherited-list h3 > button { - filter: invert(100%) brightness(160%); - } + --icon-filter: invert(100%) brightness(160%); + --caption-link-color: var(--link-color); } /* @@ -168,12 +168,12 @@ body.theme-dark { body { --body-text-color: #e8e8e8; --block-text-color: #e8e8e8; - --body-background-color: #222528; + --body-background-color: #1f2124; --section-background-color: var(--body-background-color); --detail-background-color: var(--body-background-color); --code-background-color: #303940; --mark-background-color: #313131; - --detail-block-color: #f4f4f4; + --detail-block-color: #31363c; --navbar-background-color: #395A6F; --navbar-text-color: #ffffff; --subnav-background-color: #3d454d; @@ -187,11 +187,11 @@ body.theme-dark { --odd-row-color: #2d3135; --title-color: #fff; --link-color: #94badb; - --link-color-active: #ffb45b; - --toc-background-color: #31363c; + --link-color-active: #e8a351; + --toc-background-color: #2f3439; --toc-highlight-color: var(--subnav-background-color); --toc-hover-color: #3f4146; - --snippet-background-color: #2d363c; + --snippet-background-color: #2c353b; --snippet-text-color: var(--block-text-color); --snippet-highlight-color: #f7c590; --pre-background-color: var(--snippet-background-color); @@ -209,15 +209,13 @@ body.theme-dark { --button-focus-filter: brightness(104%); --invalid-tag-background-color: #ffe6e6; --invalid-tag-text-color: #000000; - div.main-grid img, - .inherited-list h3 > button { - filter: invert(100%) brightness(160%); - } + --icon-filter: invert(100%) brightness(160%); + --caption-link-color: var(--link-color); } body.theme-light { - --body-text-color: #282828; - --block-text-color: #282828; + --body-text-color: #181818; + --block-text-color: #181818; --body-background-color: #ffffff; --section-background-color: var(--body-background-color); --detail-background-color: var(--body-background-color); @@ -233,7 +231,7 @@ body.theme-dark { --selected-text-color: #253441; --selected-link-color: #4a698a; --table-header-color: #ebeff4; - --even-row-color: #ffffff; + --even-row-color: #fdfdfe; --odd-row-color: #f0f0f2; --title-color: #2c4557; --link-color: #437291; @@ -259,10 +257,8 @@ body.theme-dark { --button-focus-filter: brightness(104%); --invalid-tag-background-color: #ffe6e6; --invalid-tag-text-color: #000000; - div.main-grid img, - .inherited-list h3 > button { - filter: none; - } + --icon-filter: none; + --caption-link-color: var(--subnav-link-color); } } /* @@ -288,6 +284,9 @@ div.main-grid { max-width: var(--max-content-width); margin: var(--content-margin); } +div.main-grid img { + filter: var(--icon-filter); +} a:link, a:visited { text-decoration:none; color:var(--link-color); @@ -909,12 +908,12 @@ ul.preview-feature-list input { .caption a:visited, .inherited-list h3 a:link, .inherited-list h3 a:visited { - color:var(--subnav-link-color); + color:var(--caption-link-color); } .caption a:hover, .caption a:active, -.inherited-list.expanded h3 a:hover, -.inherited-list.expanded h3 a:active { +.inherited-list h3 a:hover, +.inherited-list h3 a:active { color: var(--link-color-active); } div.table-tabs { @@ -1539,6 +1538,7 @@ section[class$="-details"] .detail > div { height: 1.6em; vertical-align: middle; top: -2px; + filter: var(--icon-filter); } .inherited-list h3:has(button) { padding-left: 2px; diff --git a/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java b/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java index 8615d9f1e64..00c2f017909 100644 --- a/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java +++ b/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java @@ -427,7 +427,8 @@ public class TestSearch extends JavadocTester { """, """ const pathtoroot = "./"; - loadScripts(document, 'script');""", + loadScripts(); + initTheme();""", "

", """
  • Search
  • """, From eb729f0aaa2297c3b3dbadadf40a502d2d9ed124 Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Tue, 7 Oct 2025 15:38:58 +0000 Subject: [PATCH 0089/1639] 8247776: JFR: TestThreadContextSwitches.java failed "RuntimeException: No events: expected false, was true" Reviewed-by: mgronlun --- .../event/os/TestThreadContextSwitches.java | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/test/jdk/jdk/jfr/event/os/TestThreadContextSwitches.java b/test/jdk/jdk/jfr/event/os/TestThreadContextSwitches.java index 7b3dfc79ce9..acfaecdde7d 100644 --- a/test/jdk/jdk/jfr/event/os/TestThreadContextSwitches.java +++ b/test/jdk/jdk/jfr/event/os/TestThreadContextSwitches.java @@ -28,6 +28,7 @@ import jdk.jfr.Recording; import jdk.jfr.consumer.RecordedEvent; import jdk.test.lib.jfr.EventNames; import jdk.test.lib.jfr.Events; +import jdk.test.lib.Platform; /** * @test @@ -40,15 +41,25 @@ public class TestThreadContextSwitches { private final static String EVENT_NAME = EventNames.ThreadContextSwitchRate; public static void main(String[] args) throws Throwable { - Recording recording = new Recording(); - recording.enable(EVENT_NAME); - recording.start(); - recording.stop(); - List events = Events.fromRecording(recording); - Events.hasEvents(events); - for (RecordedEvent event : events) { - System.out.println("Event: " + event); - Events.assertField(event, "switchRate").atLeast(0.0f); + while (true) { + try (Recording recording = new Recording()) { + recording.enable(EVENT_NAME); + recording.start(); + recording.stop(); + List events = Events.fromRecording(recording); + if (!events.isEmpty()) { + for (RecordedEvent event : events) { + System.out.println("Event: " + event); + Events.assertField(event, "switchRate").atLeast(0.0f); + } + return; + } + // Thread context switch rate is unreliable on Windows because + // the way processes are identified with performance counters. + if (!Platform.isWindows()) { + Events.hasEvents(events); + } + } } } } From eb835e05f9cf8a65d804b733b382ecfba5b12907 Mon Sep 17 00:00:00 2001 From: Volkan Yazici Date: Tue, 7 Oct 2025 15:57:31 +0000 Subject: [PATCH 0090/1639] 8366040: Change URL.lookupViaProviders to use ScopedValue to detect recursive lookup Reviewed-by: alanb, dfuchs --- src/java.base/share/classes/java/net/URL.java | 22 ++------- .../spi/URLStreamHandlerProvider/Basic.java | 18 ++++++- .../circular.provider.template | 48 +++++++++++++++++++ 3 files changed, 69 insertions(+), 19 deletions(-) create mode 100644 test/jdk/java/net/spi/URLStreamHandlerProvider/circular.provider.template diff --git a/src/java.base/share/classes/java/net/URL.java b/src/java.base/share/classes/java/net/URL.java index 1435d851f41..c82236b5b85 100644 --- a/src/java.base/share/classes/java/net/URL.java +++ b/src/java.base/share/classes/java/net/URL.java @@ -41,7 +41,6 @@ import java.util.ServiceLoader; import jdk.internal.access.JavaNetURLAccess; import jdk.internal.access.SharedSecrets; -import jdk.internal.misc.ThreadTracker; import jdk.internal.misc.VM; import jdk.internal.vm.annotation.AOTRuntimeSetup; import jdk.internal.vm.annotation.AOTSafeClassInitializer; @@ -1394,24 +1393,13 @@ public final class URL implements java.io.Serializable { return handler; } - private static class ThreadTrackHolder { - static final ThreadTracker TRACKER = new ThreadTracker(); - } - - private static Object tryBeginLookup() { - return ThreadTrackHolder.TRACKER.tryBegin(); - } - - private static void endLookup(Object key) { - ThreadTrackHolder.TRACKER.end(key); - } + private static final ScopedValue IN_LOOKUP = ScopedValue.newInstance(); private static URLStreamHandler lookupViaProviders(final String protocol) { - Object key = tryBeginLookup(); - if (key == null) { + if (IN_LOOKUP.isBound()) { throw new Error("Circular loading of URL stream handler providers detected"); } - try { + return ScopedValue.where(IN_LOOKUP, true).call(() -> { final ClassLoader cl = ClassLoader.getSystemClassLoader(); final ServiceLoader sl = ServiceLoader.load(URLStreamHandlerProvider.class, cl); @@ -1423,9 +1411,7 @@ public final class URL implements java.io.Serializable { return h; } return null; - } finally { - endLookup(key); - } + }); } /** diff --git a/test/jdk/java/net/spi/URLStreamHandlerProvider/Basic.java b/test/jdk/java/net/spi/URLStreamHandlerProvider/Basic.java index 9f8381a92c8..a98bf8e129e 100644 --- a/test/jdk/java/net/spi/URLStreamHandlerProvider/Basic.java +++ b/test/jdk/java/net/spi/URLStreamHandlerProvider/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -77,6 +77,7 @@ public class Basic { viaProvider("bert", KNOWN); viaBadProvider("tom", SCE); viaBadProvider("jerry", SCE); + viaCircularProvider("circular", CIRCULAR); } private static String withoutWarning(String in) { @@ -99,6 +100,12 @@ public class Basic { throw new RuntimeException("exitValue: "+ r.exitValue + ", output:[" +r.output +"]"); } }; + static final Consumer CIRCULAR = r -> { + if (r.exitValue == 0 || + !r.output.contains("Circular loading of URL stream handler providers detected")) { + throw new RuntimeException("exitValue: " + r.exitValue + ", output:[" + r.output + "]"); + } + }; static void unknownProtocol(String protocol, Consumer resultChecker) { System.out.println("\nTesting " + protocol); @@ -125,6 +132,15 @@ public class Basic { sysProps); } + static void viaCircularProvider(String protocol, Consumer resultChecker, + String... sysProps) + throws Exception + { + viaProviderWithTemplate(protocol, resultChecker, + TEST_SRC.resolve("circular.provider.template"), + sysProps); + } + static void viaProviderWithTemplate(String protocol, Consumer resultChecker, Path template, String... sysProps) diff --git a/test/jdk/java/net/spi/URLStreamHandlerProvider/circular.provider.template b/test/jdk/java/net/spi/URLStreamHandlerProvider/circular.provider.template new file mode 100644 index 00000000000..b846cc4fec6 --- /dev/null +++ b/test/jdk/java/net/spi/URLStreamHandlerProvider/circular.provider.template @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package $package; + +import java.io.IOException; +import java.net.URI; +import java.net.URL; +import java.net.URLConnection; +import java.net.URLStreamHandler; +import java.net.spi.URLStreamHandlerProvider; + +public final class Provider extends URLStreamHandlerProvider { + + private static final String PROTOCOL = "$protocol"; + + @Override + public URLStreamHandler createURLStreamHandler(String protocol) { + try { + // Trigger circular lookup + URI.create("bogus://path/to/nothing").toURL(); + } catch (Exception exception) { + throw new RuntimeException(exception); + } + throw new AssertionError("Should not have reached here!"); + } + +} From 4ca3ab62759b366fd3e0b2267925f1fa70f057b7 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Tue, 7 Oct 2025 16:41:45 +0000 Subject: [PATCH 0091/1639] 8369123: Still more small Float16 refactorings Reviewed-by: rgiulietti --- .../classes/jdk/incubator/vector/Float16.java | 52 ++++++++++++------- 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16.java b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16.java index a564cdfed0f..fe2a6bf5580 100644 --- a/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16.java +++ b/src/jdk.incubator.vector/share/classes/jdk/incubator/vector/Float16.java @@ -35,6 +35,8 @@ import static jdk.incubator.vector.Float16Consts.SIGN_BIT_MASK; import static jdk.incubator.vector.Float16Consts.EXP_BIT_MASK; import static jdk.incubator.vector.Float16Consts.SIGNIF_BIT_MASK; import static jdk.incubator.vector.Float16Consts.MAG_BIT_MASK; +import static jdk.incubator.vector.Float16Consts.EXP_BIAS; +import static jdk.incubator.vector.Float16Consts.SIGNIFICAND_WIDTH; import static java.lang.Float.float16ToFloat; import static java.lang.Float.floatToFloat16; @@ -95,19 +97,26 @@ import jdk.internal.vm.vector.Float16Math; * IEEE Standard for Floating-Point Arithmetic */ -// Currently Float16 is a value-based class and in future it is +// Currently Float16 is a value-based class and in the future it is // expected to be aligned with Value Classes and Object as described in // JEP-401 (https://openjdk.org/jeps/401). @jdk.internal.ValueBased public final class Float16 extends Number implements Comparable { - /** @serial */ + + /** + * Primitive {@code short} field to hold the bits of the {@code Float16}. + * @serial + */ private final short value; + private static final long serialVersionUID = 16; // May not be needed when a value class? // Functionality for future consideration: - // IEEEremainder / remainder operator remainder + // IEEEremainder and separate % operator remainder (which are + // defined to use different rounding modes, see JLS sections 15.4 + // and 15.17.3). // Do *not* define any public constructors /** @@ -147,8 +156,14 @@ public final class Float16 */ public static final Float16 NaN = valueOf(Float.NaN); + /** + * A constant holding a zero (0.0) of type {@code Float16}. + */ private static final Float16 ZERO = valueOf(0); + /** + * A constant holding a one (1.0) of type {@code Float16}. + */ private static final Float16 ONE = valueOf(1); /** @@ -316,10 +331,10 @@ public final class Float16 * @param value a {@code long} value. */ public static Float16 valueOf(long value) { - if (value <= -65_520L) { // -(Float16.MAX_VALUE + Float16.ulp(Float16.MAX_VALUE) / 2) + if (value <= -65_520L) { // -(MAX_VALUE + ulp(MAX_VALUE) / 2) return NEGATIVE_INFINITY; } else { - if (value >= 65_520L) { // Float16.MAX_VALUE + Float16.ulp(Float16.MAX_VALUE) / 2 + if (value >= 65_520L) { // MAX_VALUE + ulp(MAX_VALUE) / 2 return POSITIVE_INFINITY; } // Remaining range of long, the integers in approx. +/- @@ -427,9 +442,8 @@ public final class Float16 // to implement a carry out from rounding the significand. assert (0xf800 & signif_bits) == 0x0; - // Exponent bias adjust in the representation is equal to MAX_EXPONENT. return new Float16((short)(sign_bit | - ( ((exp + MAX_EXPONENT) << (PRECISION - 1)) + signif_bits ) )); + ( ((exp + EXP_BIAS) << (PRECISION - 1)) + signif_bits) )); } /** @@ -468,7 +482,7 @@ public final class Float16 // characters rather than codepoints. if (trialResult == 0.0 // handles signed zeros - || Math.abs(trialResult) > (65504.0 + 32.0) || // Float.MAX_VALUE + ulp(MAX_VALUE), + || Math.abs(trialResult) > (65504.0 + 32.0) || // MAX_VALUE + ulp(MAX_VALUE), // handles infinities too Double.isNaN(trialResult) || noDoubleRoundingToFloat16(trialResult)) { @@ -899,7 +913,7 @@ public final class Float16 */ public static int hashCode(Float16 value) { // Use bit-pattern of canonical NaN for hashing. - Float16 f16 = isNaN(value) ? Float16.NaN : value; + Float16 f16 = isNaN(value) ? NaN : value; return (int)float16ToRawShortBits(f16); } @@ -946,7 +960,7 @@ public final class Float16 */ public static short float16ToShortBits(Float16 f16) { if (isNaN(f16)) { - return Float16.NaN.value; + return NaN.value; } return f16.value; } @@ -1531,8 +1545,8 @@ public final class Float16 */ /*package*/ static int getExponent0(short bits) { // package private to be usable in java.lang.Float. - int bin16ExpBits = 0x0000_7c00 & bits; // Five exponent bits. - return (bin16ExpBits >> (PRECISION - 1)) - 15; + int bin16ExpBits = EXP_BIT_MASK & bits; // Five exponent bits. + return (bin16ExpBits >> (PRECISION - 1)) - EXP_BIAS; } /** @@ -1563,10 +1577,10 @@ public final class Float16 int exp = getExponent(f16); return switch(exp) { - case MAX_EXPONENT + 1 -> abs(f16); // NaN or infinity - case MIN_EXPONENT - 1 -> Float16.MIN_VALUE; // zero or subnormal + case MAX_EXPONENT + 1 -> abs(f16); // NaN or infinity + case MIN_EXPONENT - 1 -> MIN_VALUE; // zero or subnormal default -> { - assert exp <= MAX_EXPONENT && exp >= MIN_EXPONENT; + assert exp <= MAX_EXPONENT && exp >= MIN_EXPONENT: "Out of range exponent"; // ulp(x) is usually 2^(SIGNIFICAND_WIDTH-1)*(2^ilogb(x)) // Let float -> float16 conversion handle encoding issues. yield scalb(ONE, exp - (PRECISION - 1)); @@ -1687,8 +1701,7 @@ public final class Float16 // nonzero value by it would be guaranteed to over or // underflow; due to rounding, scaling down takes an // additional power of two which is reflected here - final int MAX_SCALE = Float16.MAX_EXPONENT + -Float16.MIN_EXPONENT + - Float16Consts.SIGNIFICAND_WIDTH + 1; + final int MAX_SCALE = MAX_EXPONENT + -MIN_EXPONENT + SIGNIFICAND_WIDTH + 1; // Make sure scaling factor is in a reasonable range scaleFactor = Math.clamp(scaleFactor, -MAX_SCALE, MAX_SCALE); @@ -1725,9 +1738,8 @@ public final class Float16 * @see Math#copySign(double, double) */ public static Float16 copySign(Float16 magnitude, Float16 sign) { - return shortBitsToFloat16((short) ((float16ToRawShortBits(sign) & SIGN_BIT_MASK) | - (float16ToRawShortBits(magnitude) & - (EXP_BIT_MASK | SIGNIF_BIT_MASK) ))); + return shortBitsToFloat16((short)((float16ToRawShortBits(sign) & SIGN_BIT_MASK) | + (float16ToRawShortBits(magnitude) & MAG_BIT_MASK))); } /** From ebeb77baaeb6d9098d7462f5ddf61d8583b1e493 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Tue, 7 Oct 2025 16:47:43 +0000 Subject: [PATCH 0092/1639] 8358058: sun/java2d/OpenGL/DrawImageBg.java Test fails intermittently Reviewed-by: azvegint, serb, psadhukhan --- test/jdk/ProblemList.txt | 1 + .../sun/java2d/OpenGL/DrawBitmaskImage.java | 173 ++++++ test/jdk/sun/java2d/OpenGL/DrawBufImgOp.java | 514 ++++++++++++++++++ test/jdk/sun/java2d/OpenGL/DrawImageBg.java | 145 +++++ test/jdk/sun/java2d/OpenGL/LargeOps.java | 138 +++++ test/jdk/sun/java2d/OpenGL/OpaqueDest.java | 180 ++++++ .../jdk/sun/java2d/OpenGL/ScaleParamsOOB.java | 198 +++++++ test/jdk/sun/java2d/OpenGL/ShapeClip.java | 140 +++++ test/jdk/sun/java2d/OpenGL/SrcMaskOps.java | 188 +++++++ .../sun/java2d/OpenGL/VolatileSubRegion.java | 166 ++++++ test/jdk/sun/java2d/OpenGL/XformVolatile.java | 146 +++++ 11 files changed, 1989 insertions(+) create mode 100644 test/jdk/sun/java2d/OpenGL/DrawBitmaskImage.java create mode 100644 test/jdk/sun/java2d/OpenGL/DrawBufImgOp.java create mode 100644 test/jdk/sun/java2d/OpenGL/DrawImageBg.java create mode 100644 test/jdk/sun/java2d/OpenGL/LargeOps.java create mode 100644 test/jdk/sun/java2d/OpenGL/OpaqueDest.java create mode 100644 test/jdk/sun/java2d/OpenGL/ScaleParamsOOB.java create mode 100644 test/jdk/sun/java2d/OpenGL/ShapeClip.java create mode 100644 test/jdk/sun/java2d/OpenGL/SrcMaskOps.java create mode 100644 test/jdk/sun/java2d/OpenGL/VolatileSubRegion.java create mode 100644 test/jdk/sun/java2d/OpenGL/XformVolatile.java diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 48a495bc238..fce7fe85069 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -248,6 +248,7 @@ sun/awt/datatransfer/SuplementaryCharactersTransferTest.java 8011371 generic-all sun/awt/shell/ShellFolderMemoryLeak.java 8197794 windows-all sun/java2d/DirectX/OverriddenInsetsTest/OverriddenInsetsTest.java 8196102 generic-all sun/java2d/DirectX/RenderingToCachedGraphicsTest/RenderingToCachedGraphicsTest.java 8196180 windows-all,macosx-all +sun/java2d/OpenGL/OpaqueDest.java#id1 8367574 macosx-all sun/java2d/SunGraphics2D/EmptyClipRenderingTest.java 8144029 macosx-all,linux-all sun/java2d/SunGraphics2D/DrawImageBilinear.java 8297175 linux-all sun/java2d/SunGraphics2D/PolyVertTest.java 6986565 generic-all diff --git a/test/jdk/sun/java2d/OpenGL/DrawBitmaskImage.java b/test/jdk/sun/java2d/OpenGL/DrawBitmaskImage.java new file mode 100644 index 00000000000..d2730593b5b --- /dev/null +++ b/test/jdk/sun/java2d/OpenGL/DrawBitmaskImage.java @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6248561 6264014 + * @key headful + * @requires (os.family != "mac") + * @summary Verifies that bitmask image copies work properly with the + * OGL pipeline when a SrcOver composite with extra alpha is involved. + * @run main/othervm -Dsun.java2d.opengl=True DrawBitmaskImage + * @run main/othervm DrawBitmaskImage + */ + +/* + * @test + * @bug 6248561 6264014 + * @key headful + * @requires (os.family == "mac") + * @summary Verifies that bitmask image copies work properly with the + * OGL pipeline when a SrcOver composite with extra alpha is involved. + * @run main/othervm -Dsun.java2d.opengl=True DrawBitmaskImage + * @run main/othervm DrawBitmaskImage + */ + +import java.awt.AlphaComposite; +import java.awt.Canvas; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Transparency; +import java.awt.Robot; +import java.awt.image.BufferedImage; +import java.awt.image.IndexColorModel; +import java.io.File; +import javax.imageio.ImageIO; + +public class DrawBitmaskImage extends Panel { + + static final int TESTW = 200, TESTH = 200; + private static volatile DrawBitmaskImage test; + private static volatile Frame frame; + + public void paint(Graphics g) { + + Graphics2D g2d = (Graphics2D)g; + g2d.setColor(Color.black); + g2d.fillRect(0, 0, getWidth(), getHeight()); + g2d.setComposite(AlphaComposite.SrcOver.derive(0.50f)); + + BufferedImage img = getGraphicsConfiguration().createCompatibleImage(50, 50, + Transparency.BITMASK); + Graphics2D gimg = img.createGraphics(); + gimg.setComposite(AlphaComposite.Src); + gimg.setColor(new Color(0, 0, 0, 0)); + gimg.fillRect(0, 0, 50, 50); + gimg.setColor(Color.red); + gimg.fillRect(10, 10, 30, 30); + gimg.dispose(); + + + g2d.drawImage(img, 10, 10, null); + + // draw a second time to ensure that the cached copy is used + g2d.drawImage(img, 80, 10, null); + } + + public Dimension getPreferredSize() { + return new Dimension(TESTW, TESTH); + } + + static void createUI() { + test = new DrawBitmaskImage(); + frame = new Frame("OpenGL DrawBitmaskImage Test"); + Panel p = new Panel(); + p.add(test); + frame.add(p); + frame.setSize(TESTW+100, TESTH+100); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + public static void main(String[] args) throws Exception { + Robot robot = new Robot(); + + EventQueue.invokeAndWait(DrawBitmaskImage::createUI); + + robot.waitForIdle(); + robot.delay(2000); + + BufferedImage capture = null; + try { + GraphicsConfiguration gc = frame.getGraphicsConfiguration(); + if (gc.getColorModel() instanceof IndexColorModel) { + System.out.println("IndexColorModel detected: " + + "test considered PASSED"); + return; + } + Point pt1 = test.getLocationOnScreen(); + Rectangle rect = new Rectangle(pt1.x, pt1.y, TESTW, TESTH); + capture = robot.createScreenCapture(rect); + } finally { + if (frame != null) { + EventQueue.invokeAndWait(frame::dispose); + } + } + + // Test background color + int pixel = capture.getRGB(5, 10); + if (pixel != 0xff000000) { + saveImage(capture); + throw new RuntimeException("Failed: Incorrect color for " + + "background (actual=" + + Integer.toHexString(pixel) + ")"); + } + + // Test pixels (allow for small error in the actual red value) + pixel = capture.getRGB(25, 25); + System.out.println("pixel1 is " + Integer.toHexString(pixel)); + + if ((pixel < 0xff7e0000) || (pixel > 0xff900000)) { + saveImage(capture); + throw new RuntimeException("Failed: Incorrect color for " + + "first pixel (actual=" + + Integer.toHexString(pixel) + ")"); + } + + pixel = capture.getRGB(95, 25); + System.out.println("pixel2 is " + Integer.toHexString(pixel)); + if ((pixel < 0xff7e0000) || (pixel > 0xff900000)) { + saveImage(capture); + throw new RuntimeException("Failed: Incorrect color for " + + "second pixel (actual=" + + Integer.toHexString(pixel) + ")"); + } + } + + static void saveImage(BufferedImage img) { + try { + File file = new File("capture.png"); + ImageIO.write(img, "png", file); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/test/jdk/sun/java2d/OpenGL/DrawBufImgOp.java b/test/jdk/sun/java2d/OpenGL/DrawBufImgOp.java new file mode 100644 index 00000000000..5d60eb7e792 --- /dev/null +++ b/test/jdk/sun/java2d/OpenGL/DrawBufImgOp.java @@ -0,0 +1,514 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6514990 + * @key headful + * @requires (os.family != "mac") + * @summary Verifies that calling + * Graphics2D.drawImage(BufferedImage, BufferedImageOp, x, y) to an + * OpenGL-accelerated destination produces the same results when performed + * in software via BufferedImageOp.filter(). + * @run main/othervm -Dsun.java2d.opengl=True DrawBufImgOp -ignore + */ + +/* + * @test + * @bug 6514990 + * @key headful + * @requires (os.family == "mac") + * @summary Verifies that calling + * Graphics2D.drawImage(BufferedImage, BufferedImageOp, x, y) to an + * OpenGL-accelerated destination produces the same results when performed + * in software via BufferedImageOp.filter(). + * @run main/othervm -Dsun.java2d.opengl=True DrawBufImgOp -ignore + */ + +import java.awt.AlphaComposite; +import java.awt.Canvas; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.image.BufferedImage; +import java.awt.image.ByteLookupTable; +import java.awt.image.ColorModel; +import java.awt.image.ConvolveOp; +import java.awt.image.IndexColorModel; +import java.awt.image.Kernel; +import java.awt.image.LookupOp; +import java.awt.image.RescaleOp; +import java.awt.image.ShortLookupTable; +import java.awt.image.VolatileImage; +import java.io.File; +import javax.imageio.ImageIO; + +/** + * REMIND: This testcase was originally intended to automatically compare + * the results of the software BufferedImageOp implementations against + * the OGL-accelerated codepaths. However, there are just too many open + * bugs in the mediaLib-based codepaths (see below), which means that + * creating the reference image may cause crashes or exceptions, + * and even if we work around those cases using the "-ignore" flag, + * the visual results of the reference image are often buggy as well + * (so the comparison will fail even though the OGL results are correct). + * Therefore, for now we will run the testcase with the "-ignore" flag + * but without the "-compare" flag, so at least it will be checking for + * any exceptions/crashes in the OGL code. When we fix all of the + * outstanding bugs with the software codepaths, we can remove the + * "-ignore" flag and maybe even restore the "-compare" flag. In the + * meantime, it also functions well as a manual testcase (with either + * the "-show" or "-dump" options). + */ +public class DrawBufImgOp extends Canvas { + + private static final int TESTW = 600; + private static final int TESTH = 500; + + private static volatile DrawBufImgOp test; + private static volatile Frame frame; + + /* + * If true, skips tests that are known to trigger bugs (which in + * turn may cause crashes, exceptions, or other artifacts). + */ + private static boolean ignore; + + // Test both pow2 and non-pow2 sized images + private static final int[] srcSizes = { 32, 17 }; + private static final int[] srcTypes = { + BufferedImage.TYPE_INT_RGB, + BufferedImage.TYPE_INT_ARGB, + BufferedImage.TYPE_INT_ARGB_PRE, + BufferedImage.TYPE_INT_BGR, + BufferedImage.TYPE_3BYTE_BGR, + BufferedImage.TYPE_4BYTE_ABGR, + BufferedImage.TYPE_USHORT_565_RGB, + BufferedImage.TYPE_BYTE_GRAY, + BufferedImage.TYPE_USHORT_GRAY, + }; + + private static final RescaleOp + rescale1band, rescale3band, rescale4band; + private static final LookupOp + lookup1bandbyte, lookup3bandbyte, lookup4bandbyte; + private static final LookupOp + lookup1bandshort, lookup3bandshort, lookup4bandshort; + private static final ConvolveOp + convolve3x3zero, convolve5x5zero, convolve7x7zero; + private static final ConvolveOp + convolve3x3noop, convolve5x5noop, convolve7x7noop; + + static { + rescale1band = new RescaleOp(0.5f, 10.0f, null); + rescale3band = new RescaleOp( + new float[] { 0.6f, 0.4f, 0.6f }, + new float[] { 10.0f, -3.0f, 5.0f }, + null); + rescale4band = new RescaleOp( + new float[] { 0.6f, 0.4f, 0.6f, 0.9f }, + new float[] { -1.0f, 5.0f, 3.0f, 1.0f }, + null); + + // REMIND: we should probably test non-zero offsets, but that + // would require massaging the source image data to avoid going + // outside the lookup table array bounds + int offset = 0; + { + byte invert[] = new byte[256]; + byte halved[] = new byte[256]; + for (int j = 0; j < 256 ; j++) { + invert[j] = (byte) (255-j); + halved[j] = (byte) (j / 2); + } + ByteLookupTable lut1 = new ByteLookupTable(offset, invert); + lookup1bandbyte = new LookupOp(lut1, null); + ByteLookupTable lut3 = + new ByteLookupTable(offset, + new byte[][] {invert, halved, invert}); + lookup3bandbyte = new LookupOp(lut3, null); + ByteLookupTable lut4 = + new ByteLookupTable(offset, + new byte[][] {invert, halved, invert, halved}); + lookup4bandbyte = new LookupOp(lut4, null); + } + + { + short invert[] = new short[256]; + short halved[] = new short[256]; + for (int j = 0; j < 256 ; j++) { + invert[j] = (short) ((255-j) * 255); + halved[j] = (short) ((j / 2) * 255); + } + ShortLookupTable lut1 = new ShortLookupTable(offset, invert); + lookup1bandshort = new LookupOp(lut1, null); + ShortLookupTable lut3 = + new ShortLookupTable(offset, + new short[][] {invert, halved, invert}); + lookup3bandshort = new LookupOp(lut3, null); + ShortLookupTable lut4 = + new ShortLookupTable(offset, + new short[][] {invert, halved, invert, halved}); + lookup4bandshort = new LookupOp(lut4, null); + } + + // 3x3 blur + float[] data3 = { + 0.1f, 0.1f, 0.1f, + 0.1f, 0.2f, 0.1f, + 0.1f, 0.1f, 0.1f, + }; + Kernel k3 = new Kernel(3, 3, data3); + + // 5x5 edge + float[] data5 = { + -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, + -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, + -1.0f, -1.0f, 24.0f, -1.0f, -1.0f, + -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, + -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, + }; + Kernel k5 = new Kernel(5, 5, data5); + + // 7x7 blur + float[] data7 = { + 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, + 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, + 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, + 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, + 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, + 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, + 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, 0.02f, + }; + Kernel k7 = new Kernel(7, 7, data7); + + convolve3x3zero = new ConvolveOp(k3, ConvolveOp.EDGE_ZERO_FILL, null); + convolve5x5zero = new ConvolveOp(k5, ConvolveOp.EDGE_ZERO_FILL, null); + convolve7x7zero = new ConvolveOp(k7, ConvolveOp.EDGE_ZERO_FILL, null); + + convolve3x3noop = new ConvolveOp(k3, ConvolveOp.EDGE_NO_OP, null); + convolve5x5noop = new ConvolveOp(k5, ConvolveOp.EDGE_NO_OP, null); + convolve7x7noop = new ConvolveOp(k7, ConvolveOp.EDGE_NO_OP, null); + } + + public void paint(Graphics g) { + + VolatileImage vimg = createVolatileImage(TESTW, TESTH); + vimg.validate(getGraphicsConfiguration()); + + Graphics2D g2d = vimg.createGraphics(); + renderTest(g2d); + g2d.dispose(); + + g.drawImage(vimg, 0, 0, null); + } + + /* + * foreach source image size (once with pow2, once with non-pow2) + * + * foreach BufferedImage type + * + * RescaleOp (1 band) + * RescaleOp (3 bands, if src has 3 bands) + * RescaleOp (4 bands, if src has 4 bands) + * + * foreach LookupTable type (once with ByteLUT, once with ShortLUT) + * LookupOp (1 band) + * LookupOp (3 bands, if src has 3 bands) + * LookupOp (4 bands, if src has 4 bands) + * + * foreach edge condition (once with ZERO_FILL, once with EDGE_NO_OP) + * ConvolveOp (3x3) + * ConvolveOp (5x5) + * ConvolveOp (7x7) + */ + private void renderTest(Graphics2D g2d) { + g2d.setColor(Color.white); + g2d.fillRect(0, 0, TESTW, TESTH); + + int yorig = 2; + int xinc = 34; + int yinc = srcSizes[0] + srcSizes[1] + 2 + 2; + + for (int srcType : srcTypes) { + int y = yorig; + + for (int srcSize : srcSizes) { + int x = 2; + System.out.printf("type=%d size=%d\n", srcType, srcSize); + + BufferedImage srcImg = makeSourceImage(srcSize, srcType); + ColorModel srcCM = srcImg.getColorModel(); + + // RescaleOp + g2d.drawImage(srcImg, rescale1band, x, y); + x += xinc; + // REMIND: 3-band RescaleOp.filter() throws IAE for images + // that contain an alpha channel (bug to be filed) + if (srcCM.getNumColorComponents() == 3 && + !(ignore && srcCM.hasAlpha())) + { + g2d.drawImage(srcImg, rescale3band, x, y); + } + x += xinc; + if (srcCM.getNumComponents() == 4) { + g2d.drawImage(srcImg, rescale4band, x, y); + } + x += xinc; + + // LookupOp + // REMIND: Our LUTs are only 256 elements long, so won't + // currently work with USHORT_GRAY data + if (srcType != BufferedImage.TYPE_USHORT_GRAY) { + g2d.drawImage(srcImg, lookup1bandbyte, x, y); + x += xinc; + if (srcCM.getNumColorComponents() == 3) { + g2d.drawImage(srcImg, lookup3bandbyte, x, y); + } + x += xinc; + if (srcCM.getNumComponents() == 4) { + g2d.drawImage(srcImg, lookup4bandbyte, x, y); + } + x += xinc; + + // REMIND: LookupOp.createCompatibleDestImage() throws + // IAE for 3BYTE_BGR/4BYTE_ABGR (bug to be filed) + if (!(ignore && + (srcType == BufferedImage.TYPE_3BYTE_BGR || + srcType == BufferedImage.TYPE_4BYTE_ABGR))) + { + g2d.drawImage(srcImg, lookup1bandshort, x, y); + x += xinc; + // REMIND: 3-band LookupOp.filter() throws IAE for + // images that contain an alpha channel + // (bug to be filed) + if (srcCM.getNumColorComponents() == 3 && + !(ignore && srcCM.hasAlpha())) + { + g2d.drawImage(srcImg, lookup3bandshort, x, y); + } + x += xinc; + if (srcCM.getNumComponents() == 4) { + g2d.drawImage(srcImg, lookup4bandshort, x, y); + } + x += xinc; + } else { + x += 3*xinc; + } + } else { + x += 6*xinc; + } + + // ConvolveOp + // REMIND: ConvolveOp.filter() throws ImagingOpException + // for 3BYTE_BGR (see 4957775) + if (srcType != BufferedImage.TYPE_3BYTE_BGR) { + g2d.drawImage(srcImg, convolve3x3zero, x, y); + x += xinc; + g2d.drawImage(srcImg, convolve5x5zero, x, y); + x += xinc; + g2d.drawImage(srcImg, convolve7x7zero, x, y); + x += xinc; + + g2d.drawImage(srcImg, convolve3x3noop, x, y); + x += xinc; + g2d.drawImage(srcImg, convolve5x5noop, x, y); + x += xinc; + g2d.drawImage(srcImg, convolve7x7noop, x, y); + x += xinc; + } else { + x += 6*xinc; + } + + y += srcSize + 2; + } + + yorig += yinc; + } + } + + private BufferedImage makeSourceImage(int size, int type) { + int s2 = size/2; + BufferedImage img = new BufferedImage(size, size, type); + Graphics2D g2d = img.createGraphics(); + g2d.setComposite(AlphaComposite.Src); + g2d.setColor(Color.orange); + g2d.fillRect(0, 0, size, size); + g2d.setColor(Color.red); + g2d.fillRect(0, 0, s2, s2); + g2d.setColor(Color.green); + g2d.fillRect(s2, 0, s2, s2); + g2d.setColor(Color.blue); + g2d.fillRect(0, s2, s2, s2); + g2d.setColor(new Color(255, 255, 0, 128)); + g2d.fillRect(s2, s2, s2, s2); + g2d.setColor(Color.pink); + g2d.fillOval(s2-3, s2-3, 6, 6); + g2d.dispose(); + return img; + } + + public BufferedImage makeReferenceImage() { + BufferedImage img = new BufferedImage(TESTW, TESTH, + BufferedImage.TYPE_INT_RGB); + Graphics2D g2d = img.createGraphics(); + renderTest(g2d); + g2d.dispose(); + return img; + } + + public Dimension getPreferredSize() { + return new Dimension(TESTW, TESTH); + } + + private static void compareImages(BufferedImage refImg, + BufferedImage testImg, + int tolerance) + { + int x1 = 0; + int y1 = 0; + int x2 = refImg.getWidth(); + int y2 = refImg.getHeight(); + + for (int y = y1; y < y2; y++) { + for (int x = x1; x < x2; x++) { + Color expected = new Color(refImg.getRGB(x, y)); + Color actual = new Color(testImg.getRGB(x, y)); + if (!isSameColor(expected, actual, tolerance)) { + saveImage("referenceimage", refImg); + saveImage("testimage", testImg); + throw new RuntimeException("Test failed at x="+x+" y="+y+ + " (expected="+expected+ + " actual="+actual+ + ")"); + } + } + } + } + + private static boolean isSameColor(Color c1, Color c2, int e) { + int r1 = c1.getRed(); + int g1 = c1.getGreen(); + int b1 = c1.getBlue(); + int r2 = c2.getRed(); + int g2 = c2.getGreen(); + int b2 = c2.getBlue(); + int rmin = Math.max(r2-e, 0); + int gmin = Math.max(g2-e, 0); + int bmin = Math.max(b2-e, 0); + int rmax = Math.min(r2+e, 255); + int gmax = Math.min(g2+e, 255); + int bmax = Math.min(b2+e, 255); + if (r1 >= rmin && r1 <= rmax && + g1 >= gmin && g1 <= gmax && + b1 >= bmin && b1 <= bmax) + { + return true; + } + return false; + } + + + static void createUI() { + test = new DrawBufImgOp(); + Panel panel = new Panel(); + panel.add(test); + frame = new Frame("OpenGL DrawBufImgOp Test"); + frame.add(panel); + frame.setSize(TESTW+100, TESTH+100); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + public static void main(String[] args) throws Exception { + + boolean show = false; + boolean dump = false; + boolean compare = false; + + for (String arg : args) { + if (arg.equals("-show")) { + show = true; + } else if (arg.equals("-dump")) { + dump = true; + } else if (arg.equals("-compare")) { + compare = true; + } else if (arg.equals("-ignore")) { + ignore = true; + } + } + + Robot robot = new Robot(); + + EventQueue.invokeAndWait(DrawBufImgOp::createUI); + + robot.waitForIdle(); + robot.delay(2000); + + BufferedImage capture = null; + try { + GraphicsConfiguration gc = frame.getGraphicsConfiguration(); + if (gc.getColorModel() instanceof IndexColorModel) { + System.out.println("IndexColorModel detected: " + + "test considered PASSED"); + return; + } + Point pt1 = test.getLocationOnScreen(); + Rectangle rect = new Rectangle(pt1.x, pt1.y, TESTW, TESTH); + capture = robot.createScreenCapture(rect); + } finally { + if (frame != null) { + EventQueue.invokeAndWait(frame::dispose); + } + } + + // Compare the images (allow for +/- 1 bit differences in color comps) + if (dump || compare) { + BufferedImage ref = test.makeReferenceImage(); + if (dump) { + saveImage("DrawBufImgOp_ref", ref); + saveImage("DrawBufImgOp_cap", capture); + } + if (compare) { + test.compareImages(ref, capture, 1); + } + } + } + + static void saveImage(String name, BufferedImage img) { + try { + File file = new File(name + ".png"); + ImageIO.write(img, "png", file); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/test/jdk/sun/java2d/OpenGL/DrawImageBg.java b/test/jdk/sun/java2d/OpenGL/DrawImageBg.java new file mode 100644 index 00000000000..7fc38d91b06 --- /dev/null +++ b/test/jdk/sun/java2d/OpenGL/DrawImageBg.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4993274 + * @key headful + * @requires (os.family != "mac") + * @summary Verifies that managed image copies and transforms work properly + * with the OGL pipeline when a background color is specified. + * @run main/othervm -Dsun.java2d.opengl=True DrawImageBg + * @run main/othervm DrawImageBg + */ + +/* + * @test + * @bug 4993274 + * @key headful + * @requires (os.family == "mac") + * @summary Verifies that managed image copies and transforms work properly + * with the OGL pipeline when a background color is specified. + * @run main/othervm -Dsun.java2d.opengl=True DrawImageBg + * @run main/othervm DrawImageBg + */ + +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.Transparency; +import java.awt.image.BufferedImage; +import java.io.File; +import javax.imageio.ImageIO; + +public class DrawImageBg extends Panel { + + static volatile Frame frame; + static volatile DrawImageBg test; + + public void paint(Graphics g) { + + Graphics2D g2d = (Graphics2D)g; + g2d.setColor(Color.black); + g2d.fillRect(0, 0, getWidth(), getHeight()); + + BufferedImage img = getGraphicsConfiguration().createCompatibleImage(50, 50, + Transparency.BITMASK); + Graphics2D gimg = img.createGraphics(); + gimg.setComposite(AlphaComposite.Src); + gimg.setColor(new Color(0, 0, 0, 0)); + gimg.fillRect(0, 0, 50, 50); + gimg.setColor(Color.red); + gimg.fillRect(10, 10, 30, 30); + gimg.dispose(); + + g2d.drawImage(img, 10, 10, Color.blue, null); + + // draw a second time to ensure that the cached copy is used + g2d.drawImage(img, 80, 10, Color.blue, null); + } + + static void createUI() { + frame = new Frame("OpenGL DrawImageBg Test"); + test = new DrawImageBg(); + frame.add(test); + frame.setSize(300, 300); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + public static void main(String[] args) throws Exception { + + BufferedImage capture = null; + Robot robot = new Robot(); + try { + EventQueue.invokeAndWait(DrawImageBg::createUI); + robot.waitForIdle(); + robot.delay(3000); + + // Grab the screen region + Point pt1 = test.getLocationOnScreen(); + Rectangle rect = new Rectangle(pt1.x+80, pt1.y, 80, 80); + capture = robot.createScreenCapture(rect); + } finally { + if (frame != null) { + EventQueue.invokeAndWait(frame::dispose); + } + } + + if (capture == null) { + throw new RuntimeException("Screen capture is null"); + } + + // Test inner and outer pixels + int pixel1 = capture.getRGB(5, 10); + if (pixel1 != 0xff0000ff) { + saveImage(capture); + throw new RuntimeException(getMsg("outer", pixel1)); + } + int pixel2 = capture.getRGB(25, 25); + if (pixel2 != 0xffff0000) { + saveImage(capture); + throw new RuntimeException(getMsg("inner", pixel2)); + } + } + + static String getMsg(String r, int p1) { + return "Failed: Incorrect color for " + r + " pixel: got " + Integer.toHexString(p1); + } + + static void saveImage(BufferedImage img) { + try { + File file = new File("capture.png"); + ImageIO.write(img, "png", file); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/test/jdk/sun/java2d/OpenGL/LargeOps.java b/test/jdk/sun/java2d/OpenGL/LargeOps.java new file mode 100644 index 00000000000..ace60b7a3c4 --- /dev/null +++ b/test/jdk/sun/java2d/OpenGL/LargeOps.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6219284 6358147 6274813 6578452 + * @key headful + * @summary Verifies that OGLRenderer.drawPoly(), + * OGLTextRenderer.drawGlyphList(), and OGLMaskFill work properly when the + * operation parameters exceed the capacity of the render queue. With the + * single-threaded OpenGL pipeline, there are some operations that require + * a separate buffer to be spawned if the parameters cannot fit entirely on + * the standard buffer. This test exercises this special case. + * @run main/othervm -Dsun.java2d.opengl=True -Dsun.java2d.opengl.lcdshader=true LargeOps + */ + +import java.awt.Canvas; +import java.awt.Color; +import java.awt.EventQueue; +import java.awt.Font; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.Robot; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.image.BufferedImage; +import java.io.File; +import javax.imageio.ImageIO; + +public class LargeOps extends Canvas { + + private static final int NUM_POINTS = 8000; + private int[] xPoints, yPoints; + private String str; + + public LargeOps() { + xPoints = new int[NUM_POINTS]; + yPoints = new int[NUM_POINTS]; + for (int i = 0; i < NUM_POINTS; i++) { + xPoints[i] = (i % 2 == 0) ? 10 : 400; + yPoints[i] = (i % 2 == 1) ? i+3 : i; + } + + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < NUM_POINTS; i+=11) { + sb.append("ThisIsATest"); + } + str = sb.toString(); + } + + public void paint(Graphics g) { + Graphics2D g2d = (Graphics2D)g; + g2d.setColor(Color.white); + g2d.fillRect(0, 0, getWidth(), getHeight()); + + // draw large polyline + g2d.setColor(Color.green); + g2d.drawPolyline(xPoints, yPoints, NUM_POINTS); + + // draw long string + g2d.setColor(Color.blue); + g2d.drawString(str, 10, 100); + + // draw long string with larger pt size + Font font = g2d.getFont(); + g2d.setFont(font.deriveFont(40.0f)); + g2d.drawString(str, 10, 150); + + // do the same with LCD hints enabled + g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, + RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB); + g2d.setFont(font); + g2d.drawString(str, 10, 200); + g2d.setFont(font.deriveFont(43.0f)); + g2d.drawString(str, 10, 250); + + g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, + RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HBGR); + g2d.setFont(font); + g2d.drawString(str, 10, 300); + g2d.setFont(font.deriveFont(37.0f)); + g2d.drawString(str, 10, 350); + } + + static volatile Frame frame; + static volatile LargeOps test; + + static void createUI() { + frame = new Frame("OpenGL LargeOps Test"); + frame.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + frame.dispose(); + } + }); + test = new LargeOps(); + frame.add(test); + frame.setSize(600, 600); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + public static void main(String[] args) throws Exception { + try { + Robot robot = new Robot(); + EventQueue.invokeAndWait(LargeOps::createUI); + robot.waitForIdle(); + robot.delay(6000); + } finally { + if (frame != null) { + EventQueue.invokeAndWait(frame::dispose); + } + } + } +} diff --git a/test/jdk/sun/java2d/OpenGL/OpaqueDest.java b/test/jdk/sun/java2d/OpenGL/OpaqueDest.java new file mode 100644 index 00000000000..50896316109 --- /dev/null +++ b/test/jdk/sun/java2d/OpenGL/OpaqueDest.java @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6277977 6319663 + * @key headful + * @requires (os.family != "mac") + * @summary Verifies that blending operations do not inadvertantly leave + * non-opaque alpha values in the framebuffer. Note that this test is + * intended to run on GraphicsConfigs that support a stored alpha channel + * (to verify the bug at hand), but it is also a useful for testing the + * compositing results on any configuration. + * @run main/othervm -Dsun.java2d.opengl=True OpaqueDest + * @run main/othervm OpaqueDest + */ + +/* + * @test + * @bug 6277977 6319663 + * @key headful + * @requires (os.family == "mac") + * @summary Verifies that blending operations do not inadvertantly leave + * non-opaque alpha values in the framebuffer. Note that this test is + * intended to run on GraphicsConfigs that support a stored alpha channel + * (to verify the bug at hand), but it is also a useful for testing the + * compositing results on any configuration. + * @run main/othervm -Dsun.java2d.opengl=True OpaqueDest + * @run main/othervm OpaqueDest + */ + +import java.awt.AlphaComposite; +import java.awt.Canvas; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.image.BufferedImage; +import java.awt.image.IndexColorModel; +import java.io.File; +import javax.imageio.ImageIO; + +public class OpaqueDest extends Canvas { + + private static volatile Frame frame; + private static volatile OpaqueDest test; + + public void paint(Graphics g) { + + Graphics2D g2d = (Graphics2D)g; + + g2d.setColor(Color.red); + g2d.fillRect(0, 0, getWidth(), getHeight()); + + // This will clear the rectangle to black + g2d.setComposite(AlphaComposite.Clear); + g2d.fillRect(10, 10, 80, 80); + + // If everything is working properly, then this will fill the + // rectangle with red again. Before this bug was fixed, the previous + // Clear operation would leave zero values in the destination's + // alpha channel (if present), and therefore a SrcIn operation + // would result in all-black. + g2d.setComposite(AlphaComposite.SrcIn); + g2d.fillRect(10, 10, 80, 80); + } + + public Dimension getPreferredSize() { + return new Dimension(100, 100); + } + + static void createUI() { + test = new OpaqueDest(); + frame = new Frame("OpenGL OpaqueDest Test"); + Panel p = new Panel(); + p.add(test); + frame.add(p); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + public static void main(String[] args) throws Exception { + Robot robot = new Robot(); + + EventQueue.invokeAndWait(OpaqueDest::createUI); + + robot.waitForIdle(); + robot.delay(2000); + + BufferedImage capture = null; + try { + GraphicsConfiguration gc = frame.getGraphicsConfiguration(); + if (gc.getColorModel() instanceof IndexColorModel) { + System.out.println("IndexColorModel detected: " + + "test considered PASSED"); + return; + } + Point pt1 = test.getLocationOnScreen(); + Rectangle rect = new Rectangle(pt1.x, pt1.y, 100, 100); + capture = robot.createScreenCapture(rect); + } finally { + if (frame != null) { + EventQueue.invokeAndWait(frame::dispose); + } + } + + + // Test all pixels (every one should be red) + for (int y = 0; y < 100; y++) { + for (int x = 0; x < 100; x++) { + int actual = capture.getRGB(x, y); + int expected = 0xffff0000; + if (!similar(actual, expected)) { + saveImage(capture); + throw new RuntimeException("Test failed at x="+x+" y="+y+ + " (expected="+ + Integer.toHexString(expected) + + " actual="+ + Integer.toHexString(actual) + + ")"); + } + } + } + } + + static boolean similar(int p1, int p2) { + int a1 = (p1 >> 24) & 0xff; + int r1 = (p1 >> 16) & 0xff; + int g1 = (p1 >> 8) & 0xff; + int b1 = p1 & 0xff; + int a2 = (p2 >> 24) & 0xff; + int r2 = (p2 >> 16) & 0xff; + int g2 = (p2 >> 8) & 0xff; + int b2 = p2 & 0xff; + + int allowedDiff = 0x01; // tiny rounding error allowed. + return + (Math.abs(a1 - a2) <= allowedDiff) && + (Math.abs(r1 - r2) <= allowedDiff) && + (Math.abs(g1 - g2) <= allowedDiff) && + (Math.abs(b1 - b2) <= allowedDiff); + } + + static void saveImage(BufferedImage img) { + try { + File file = new File("capture.png"); + ImageIO.write(img, "png", file); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/test/jdk/sun/java2d/OpenGL/ScaleParamsOOB.java b/test/jdk/sun/java2d/OpenGL/ScaleParamsOOB.java new file mode 100644 index 00000000000..b3d866cfd75 --- /dev/null +++ b/test/jdk/sun/java2d/OpenGL/ScaleParamsOOB.java @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 5104584 8237244 + * @key headful + * @requires (os.family != "mac") + * @summary Verifies that scaling an image works properly when the + * source parameters are outside the source bounds. + * @run main/othervm -Dsun.java2d.opengl=True ScaleParamsOOB + * @run main/othervm ScaleParamsOOB + */ + +/* + * @test + * @bug 5104584 8237244 + * @key headful + * @requires (os.family == "mac") + * @summary Verifies that scaling an image works properly when the + * source parameters are outside the source bounds. + * @run main/othervm -Dsun.java2d.opengl=True ScaleParamsOOB + * @run main/othervm ScaleParamsOOB + */ + + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.image.BufferedImage; +import java.io.File; +import javax.imageio.ImageIO; + +public class ScaleParamsOOB extends Panel { + + private static final int TOLERANCE = 12; + + private static volatile ScaleParamsOOB test; + private static volatile Frame frame; + + private BufferedImage img; + + public void paint(Graphics g) { + + Graphics2D g2d = (Graphics2D)g; + g2d.setColor(Color.black); + g2d.fillRect(0, 0, getWidth(), getHeight()); + + BufferedImage img = getGraphicsConfiguration().createCompatibleImage(40, 40); + Graphics2D gimg = img.createGraphics(); + gimg.setColor(Color.red); + gimg.fillRect(0, 0, 40, 40); + gimg.dispose(); + + // first time will be a sw->surface blit + g2d.drawImage(img, + 10, 10, 90, 90, + -60, -60, 100, 100, + null); + + // second time will be a texture->surface blit + g2d.drawImage(img, + 110, 10, 190, 90, + -60, -60, 100, 100, + null); + } + + public Dimension getPreferredSize() { + return new Dimension(300, 200); + } + + private static void testRegion(BufferedImage bi, + Rectangle wholeRegion, + Rectangle affectedRegion) + { + int x1 = wholeRegion.x; + int y1 = wholeRegion.y; + int x2 = x1 + wholeRegion.width; + int y2 = y1 + wholeRegion.height; + + for (int y = y1; y < y2; y++) { + for (int x = x1; x < x2; x++) { + int actual = bi.getRGB(x, y); + int expected = 0; + if (affectedRegion.contains(x, y)) { + expected = Color.red.getRGB(); + } else { + expected = Color.black.getRGB(); + } + int alpha = (actual >> 24) & 0xFF; + int red = (actual >> 16) & 0xFF; + int green = (actual >> 8) & 0xFF; + int blue = (actual) & 0xFF; + + int standardAlpha = (expected >> 24) & 0xFF; + int standardRed = (expected >> 16) & 0xFF; + int standardGreen = (expected >> 8) & 0xFF; + int standardBlue = (expected) & 0xFF; + + if ((Math.abs(alpha - standardAlpha) > TOLERANCE) || + (Math.abs(red - standardRed) > TOLERANCE) || + (Math.abs(green - standardGreen) > TOLERANCE) || + (Math.abs(blue - standardBlue) > TOLERANCE)) { + saveImage(bi); + throw new RuntimeException("Test failed at x="+x+" y="+y+ + " (expected="+ + Integer.toHexString(expected) + + " actual="+ + Integer.toHexString(actual) + + ")"); + } + } + } + } + + private static void createAndShowGUI() { + test = new ScaleParamsOOB(); + frame = new Frame("OpenGL ScaleParamsOOB Test"); + frame.setAlwaysOnTop(true); + frame.add(test); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + public static void main(String[] args) throws Exception { + Robot robot = new Robot(); + + EventQueue.invokeAndWait(() -> createAndShowGUI()); + + robot.waitForIdle(); + robot.delay(2000); + + // Grab the screen region + BufferedImage capture = null; + try { + Point pt1 = test.getLocationOnScreen(); + Rectangle rect = new Rectangle(pt1.x, pt1.y, 200, 200); + capture = robot.createScreenCapture(rect); + } finally { + if (frame != null) { + EventQueue.invokeAndWait(frame::dispose); + } + } + + // Test background color + int pixel = capture.getRGB(5, 5); + if (pixel != 0xff000000) { + saveImage(capture); + throw new RuntimeException("Failed: Incorrect color for " + + "background: " + Integer.toHexString(pixel)); + } + + // Test pixels + testRegion(capture, + new Rectangle(5, 5, 90, 90), + new Rectangle(40, 40, 20, 20)); + testRegion(capture, + new Rectangle(105, 5, 90, 90), + new Rectangle(140, 40, 20, 20)); + } + + static void saveImage(BufferedImage img) { + try { + File file = new File("capture.png"); + ImageIO.write(img, "png", file); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/test/jdk/sun/java2d/OpenGL/ShapeClip.java b/test/jdk/sun/java2d/OpenGL/ShapeClip.java new file mode 100644 index 00000000000..f50b7aff5a6 --- /dev/null +++ b/test/jdk/sun/java2d/OpenGL/ShapeClip.java @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 5002133 + * @key headful + * @requires (os.family != "mac") + * @summary Verifies that the OpenGL pipeline does not affect the color + * buffer when setting up a complex (shape) clip region. The test fails if + * the circular clip region is filled with a green color (the green region + * should not be visible at all). + * @run main/othervm -Dsun.java2d.opengl=True ShapeClip + * @run main/othervm ShapeClip + */ + +/* + * @test + * @bug 5002133 + * @key headful + * @requires (os.family == "mac") + * @summary Verifies that the OpenGL pipeline does not affect the color + * buffer when setting up a complex (shape) clip region. The test fails if + * the circular clip region is filled with a green color (the green region + * should not be visible at all). + * @run main/othervm -Dsun.java2d.opengl=True ShapeClip + * @run main/othervm ShapeClip + */ + +import java.awt.Color; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.geom.Ellipse2D; +import java.awt.image.BufferedImage; +import java.io.File; +import javax.imageio.ImageIO; + +public class ShapeClip extends Panel { + + private static volatile Frame frame; + private static volatile ShapeClip test; + + public void paint(Graphics g) { + + Graphics2D g2d = (Graphics2D)g; + + int width = getWidth(); + int height = getHeight(); + + g2d.setColor(Color.black); + g2d.fillRect(0, 0, width, height); + + g2d.setColor(Color.green); + g2d.fillRect(0, 0, 1, 1); + g2d.setClip(new Ellipse2D.Double(10, 10, 100, 100)); + g2d.setColor(Color.blue); + g2d.fillRect(30, 30, 20, 20); + } + + static void createUI() { + test = new ShapeClip(); + frame = new Frame("OpenGL ShapeClip Test"); + frame.add(test); + frame.setSize(200, 200); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + public static void main(String[] args) throws Exception { + Robot robot = new Robot(); + + EventQueue.invokeAndWait(ShapeClip::createUI); + + robot.waitForIdle(); + robot.delay(2000); + + // Grab the screen region + BufferedImage capture = null; + try { + Point pt1 = test.getLocationOnScreen(); + Rectangle rect = new Rectangle(pt1.x, pt1.y, 80, 80); + capture = robot.createScreenCapture(rect); + } finally { + if (frame != null) { + EventQueue.invokeAndWait(frame::dispose); + } + } + + // Test blue rectangle + int pixel1 = capture.getRGB(40, 40); + if (pixel1 != 0xff0000ff) { + saveImage(capture); + throw new RuntimeException("Failed: Incorrect color for " + + "rectangle " + Integer.toHexString(pixel1)); + } + + // Test clip region (should be same color as background) + int pixel2 = capture.getRGB(60, 40); + if (pixel2 != 0xff000000) { + saveImage(capture); + throw new RuntimeException("Failed: Incorrect color for " + + "clip region " + Integer.toHexString(pixel2)); + } + } + + static void saveImage(BufferedImage img) { + try { + File file = new File("capture.png"); + ImageIO.write(img, "png", file); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/test/jdk/sun/java2d/OpenGL/SrcMaskOps.java b/test/jdk/sun/java2d/OpenGL/SrcMaskOps.java new file mode 100644 index 00000000000..9908cffdefb --- /dev/null +++ b/test/jdk/sun/java2d/OpenGL/SrcMaskOps.java @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4942939 4970674 + * @key headful + * @requires (os.family != "mac") + * @summary Verifies that OGLMaskFill, OGLMaskBlit, and OGLTextRenderer + * operations work properly for non-SrcOver composites. + * @run main/othervm -Dsun.java2d.opengl=True SrcMaskOps + * @run main/othervm SrcMaskOps + */ + +/* + * @test + * @bug 4942939 4970674 + * @key headful + * @requires (os.family == "mac") + * @summary Verifies that OGLMaskFill, OGLMaskBlit, and OGLTextRenderer + * operations work properly for non-SrcOver composites. + * @run main/othervm -Dsun.java2d.opengl=True SrcMaskOps + * @run main/othervm SrcMaskOps + */ + +import java.awt.AlphaComposite; +import java.awt.Color; +import java.awt.EventQueue; +import java.awt.Font; +import java.awt.Frame; +import java.awt.GradientPaint; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.Robot; +import java.awt.image.BufferedImage; +import java.io.File; +import javax.imageio.ImageIO; + +public class SrcMaskOps extends Panel { + + static volatile Frame frame; + static volatile SrcMaskOps test; + + static final int SRX = 50; + static final int SRY = 50; + static final int GPX = 90; + static final int GPY = 50; + static final int DTX = 120; + static final int DTY = 70; + + public void paint(Graphics g) { + + Graphics2D g2d = (Graphics2D)g; + + g2d.setColor(Color.white); + g2d.fillRect(0, 0, getWidth(), getHeight()); + + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setComposite(AlphaComposite.Src); + + g2d.setColor(Color.blue); + g2d.drawRect(SRX, SRY, 20, 20); + + g2d.setPaint(new GradientPaint(0.0f, 0.0f, Color.red, + 100.0f, 100.f, Color.red, true)); + g2d.drawRect(GPX, GPY, 20, 20); + + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_OFF); + + g2d.setColor(Color.red); + Font font = new Font(Font.DIALOG, Font.PLAIN, 20); + g2d.setFont(font); + g2d.drawString("HELLO", DTX, DTY); + } + + static void createUI() { + frame = new Frame("OpenGL SrcMaskOps Test"); + test = new SrcMaskOps(); + frame.add(test); + frame.setSize(300, 300); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + public static void main(String[] args) throws Exception { + + Robot robot = new Robot(); + BufferedImage capture = null; + try { + EventQueue.invokeAndWait(SrcMaskOps::createUI); + robot.waitForIdle(); + robot.delay(3000); + + // Grab the screen region + Point pt1 = test.getLocationOnScreen(); + Rectangle rect = new Rectangle(pt1.x, pt1.y, 300, 300); + capture = robot.createScreenCapture(rect); + } finally { + if (frame != null) { + EventQueue.invokeAndWait(frame::dispose); + } + } + + // Test solid rectangle + int pixel1, pixel2; + pixel1 = capture.getRGB(SRX, SRY); + pixel2 = capture.getRGB(SRX+2, SRY+2); + if (!similar(pixel1, 0xff0000ff) || !similar(pixel2, 0xffffffff)) { + saveImage(capture); + throw new RuntimeException(getMsg("solid rectangle", pixel1, pixel2)); + } + + // Test GradientPaint rectangle + pixel1 = capture.getRGB(GPX, GPY); + pixel2 = capture.getRGB(GPX+2, GPY+2); + if (!similar(pixel1, 0xffff0000) || !similar(pixel2, 0xffffffff)) { + saveImage(capture); + throw new RuntimeException(getMsg("GradientPaint rectangle", pixel1, pixel2)); + } + + // Test solid text + pixel1 = capture.getRGB(DTX+2, DTY-5); + pixel2 = capture.getRGB(DTX+5, DTY-5); + if (!similar(pixel1, 0xffff0000) || !similar(pixel2, 0xffffffff)) { + saveImage(capture); + throw new RuntimeException(getMsg("solid text", pixel1, pixel2)); + } + + } + + static boolean similar(int p1, int p2) { + int a1 = (p1 >> 24) & 0xff; + int r1 = (p1 >> 16) & 0xff; + int g1 = (p1 >> 8) & 0xff; + int b1 = p1 & 0xff; + int a2 = (p2 >> 24) & 0xff; + int r2 = (p2 >> 16) & 0xff; + int g2 = (p2 >> 8) & 0xff; + int b2 = p2 & 0xff; + + int allowedDiff = 0x10; + return + (Math.abs(a1 - a2) <= allowedDiff) && + (Math.abs(r1 - r2) <= allowedDiff) && + (Math.abs(g1 - g2) <= allowedDiff) && + (Math.abs(b1 - b2) <= allowedDiff); + } + + static String getMsg(String r, int p1, int p2) { + return "Failed: Incorrect color[s] for " + r + " got " + + Integer.toHexString(p1) + " and " + Integer.toHexString(p2); + } + + static void saveImage(BufferedImage img) { + try { + File file = new File("capture.png"); + ImageIO.write(img, "png", file); + } catch (Exception e) { + e.printStackTrace(); + } + } +} diff --git a/test/jdk/sun/java2d/OpenGL/VolatileSubRegion.java b/test/jdk/sun/java2d/OpenGL/VolatileSubRegion.java new file mode 100644 index 00000000000..7ec350bc958 --- /dev/null +++ b/test/jdk/sun/java2d/OpenGL/VolatileSubRegion.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6244071 + * @key headful + * @requires (os.family != "mac") + * @summary Verifies that copying a subregion from a VolatileImage works + * properly with the OGL pipeline. + * @run main/othervm VolatileSubRegion + * @run main/othervm -Dsun.java2d.opengl=True -Dsun.java2d.opengl.fbobject=true VolatileSubRegion + * @run main/othervm -Dsun.java2d.opengl=True -Dsun.java2d.opengl.fbobject=false VolatileSubRegion + */ + +/* + * @test + * @bug 6244071 + * @key headful + * @requires (os.family == "mac") + * @summary Verifies that copying a subregion from a VolatileImage works + * properly with the OGL pipeline. + * @run main/othervm VolatileSubRegion + * @run main/othervm -Dsun.java2d.opengl=True -Dsun.java2d.opengl.fbobject=true VolatileSubRegion + * @run main/othervm -Dsun.java2d.opengl=True -Dsun.java2d.opengl.fbobject=false VolatileSubRegion + */ + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GraphicsConfiguration; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.image.BufferedImage; +import java.awt.image.IndexColorModel; +import java.awt.image.VolatileImage; +import java.io.File; +import javax.imageio.ImageIO; + +public class VolatileSubRegion extends Panel { + + private VolatileImage img; + + public void paint(Graphics g) { + + Graphics2D g2d = (Graphics2D)g; + + if (img == null) { + img = createVolatileImage(200, 200); + Graphics2D goff = img.createGraphics(); + goff.setColor(Color.green); + goff.fillRect(50, 0, 100, 50); + goff.setColor(Color.blue); + goff.fillRect(0, 0, 200, 200); + goff.setColor(Color.red); + goff.fillRect(50, 50, 100, 100); + goff.setColor(Color.yellow); + goff.fillRect(50, 150, 100, 50); + goff.dispose(); + } + + g2d.setColor(Color.white); + g2d.fillRect(0, 0, getWidth(), getHeight()); + + g2d.drawImage(img, + 50, 50, 200, 200, + 50, 50, 200, 200, + null); + + } + + + private static volatile VolatileSubRegion test; + private static volatile Frame frame; + + static void createUI() { + test = new VolatileSubRegion(); + frame = new Frame("OpenGL VolatileSubRegion Test"); + frame.add(test); + frame.setSize(300, 300); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + public static void main(String[] args) throws Exception { + Robot robot = new Robot(); + + EventQueue.invokeAndWait(VolatileSubRegion::createUI); + + robot.waitForIdle(); + robot.delay(2000); + + BufferedImage capture = null; + try { + GraphicsConfiguration gc = frame.getGraphicsConfiguration(); + if (gc.getColorModel() instanceof IndexColorModel) { + System.out.println("IndexColorModel detected: " + + "test considered PASSED"); + return; + } + Point pt1 = test.getLocationOnScreen(); + Rectangle rect = new Rectangle(pt1.x, pt1.y, 200, 200); + capture = robot.createScreenCapture(rect); + } finally { + if (frame != null) { + EventQueue.invokeAndWait(frame::dispose); + } + } + + // Test pixels + int pixel1 = capture.getRGB(49, 50); + if (pixel1 != 0xffffffff) { + saveImage(capture); + throw new RuntimeException(getMsg("background pixel", pixel1)); + } + int pixel2 = capture.getRGB(50, 50); + if (pixel2 != 0xffff0000) { + saveImage(capture); + throw new RuntimeException(getMsg("red region", pixel2)); + } + int pixel3 = capture.getRGB(50, 150); + if (pixel3 != 0xffffff00) { + saveImage(capture); + throw new RuntimeException(getMsg("yellow region", pixel3)); + } + } + + static String getMsg(String r, int p1) { + return "Failed: Incorrect color for " + r + " : got " + Integer.toHexString(p1); + } + + static void saveImage(BufferedImage img) { + try { + File file = new File("capture.png"); + ImageIO.write(img, "png", file); + } catch (Exception e) { + e.printStackTrace(); + } + } + +} diff --git a/test/jdk/sun/java2d/OpenGL/XformVolatile.java b/test/jdk/sun/java2d/OpenGL/XformVolatile.java new file mode 100644 index 00000000000..44e7c7ee8ba --- /dev/null +++ b/test/jdk/sun/java2d/OpenGL/XformVolatile.java @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4970836 + * @key headful + * @requires (os.family != "mac") + * @summary Verifies that transformed VolatileImage copies work properly with + * the OGL pipeline. + * @run main/othervm XformVolatile + * @run main/othervm -Dsun.java2d.opengl=True -Dsun.java2d.opengl.fbobject=true XformVolatile + * @run main/othervm -Dsun.java2d.opengl=True -Dsun.java2d.opengl.fbobject=false XformVolatile + */ + +/* + * @test + * @bug 4970836 + * @key headful + * @requires (os.family == "mac") + * @summary Verifies that transformed VolatileImage copies work properly with + * the OGL pipeline. + * @run main/othervm XformVolatile + * @run main/othervm -Dsun.java2d.opengl=True -Dsun.java2d.opengl.fbobject=true XformVolatile + * @run main/othervm -Dsun.java2d.opengl=True -Dsun.java2d.opengl.fbobject=false XformVolatile + */ + +import java.awt.Color; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.image.BufferedImage; +import java.awt.image.VolatileImage; +import java.io.File; +import javax.imageio.ImageIO; + +public class XformVolatile extends Panel { + + private static volatile Frame frame; + private static volatile XformVolatile test; + private volatile VolatileImage img; + + public void paint(Graphics g) { + + Graphics2D g2d = (Graphics2D)g; + + if (img == null) { + img = createVolatileImage(200, 200); + Graphics2D goff = img.createGraphics(); + goff.setColor(Color.blue); + goff.fillRect(0, 0, 200, 200); + goff.setColor(Color.red); + goff.fillPolygon(new int[] {10, 100, 190}, + new int[] {190, 10, 190}, 3); + goff.dispose(); + } + + g2d.setColor(Color.black); + g2d.fillRect(0, 0, getWidth(), getHeight()); + + g2d.rotate(Math.toRadians(3.0)); + g2d.drawImage(img, 0, 0, null); + } + + static void createUI() { + test = new XformVolatile(); + frame = new Frame("OpenGL XformVolatile Test"); + frame.add(test); + frame.setSize(300, 300); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + public static void main(String[] args) throws Exception { + + Robot robot = new Robot(); + + EventQueue.invokeAndWait(XformVolatile::createUI); + + robot.waitForIdle(); + robot.delay(2000); + + // Grab the screen region + BufferedImage capture = null; + try { + Point pt1 = test.getLocationOnScreen(); + Rectangle rect = new Rectangle(pt1.x, pt1.y, 200, 200); + capture = robot.createScreenCapture(rect); + } finally { + if (frame != null) { + EventQueue.invokeAndWait(frame::dispose); + } + } + + // Test inner and outer pixels + int pixel1 = capture.getRGB(5, 175); + if (pixel1 != 0xff0000ff) { + saveImage(capture); + throw new RuntimeException(getMsg("inner", pixel1)); + } + int pixel2 = capture.getRGB(5, 188); + if (pixel2 != 0xffff0000) { + saveImage(capture); + throw new RuntimeException(getMsg("inner", pixel2)); + } + } + + static String getMsg(String r, int p1) { + return "Failed: Incorrect color for " + r + " pixel: got " + Integer.toHexString(p1); + } + + static void saveImage(BufferedImage img) { + try { + File file = new File("capture.png"); + ImageIO.write(img, "png", file); + } catch (Exception e) { + e.printStackTrace(); + } + } +} From 1ea8cfa6dc8e6f96fd87553331abaae17ec173ea Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Tue, 7 Oct 2025 16:54:36 +0000 Subject: [PATCH 0093/1639] 8369226: GHA: Switch to MacOS 15 Reviewed-by: erikj, ayang, sgehwolf --- .github/workflows/main.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 0d8663fab1a..4d1e8a8be3d 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -327,8 +327,8 @@ jobs: uses: ./.github/workflows/build-macos.yml with: platform: macos-x64 - runs-on: 'macos-13' - xcode-toolset-version: '14.3.1' + runs-on: 'macos-15-intel' + xcode-toolset-version: '16.4' configure-arguments: ${{ github.event.inputs.configure-arguments }} make-arguments: ${{ github.event.inputs.make-arguments }} dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} @@ -340,8 +340,8 @@ jobs: uses: ./.github/workflows/build-macos.yml with: platform: macos-aarch64 - runs-on: 'macos-14' - xcode-toolset-version: '15.4' + runs-on: 'macos-15' + xcode-toolset-version: '16.4' configure-arguments: ${{ github.event.inputs.configure-arguments }} make-arguments: ${{ github.event.inputs.make-arguments }} dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} @@ -432,9 +432,9 @@ jobs: with: platform: macos-aarch64 bootjdk-platform: macos-aarch64 - runs-on: macos-14 + runs-on: macos-15 dry-run: ${{ needs.prepare.outputs.dry-run == 'true' }} - xcode-toolset-version: '15.4' + xcode-toolset-version: '16.4' debug-suffix: -debug test-windows-x64: From 6b3162620bd808227ec7b4331ae6fc32ceb909e8 Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Tue, 7 Oct 2025 17:21:13 +0000 Subject: [PATCH 0094/1639] 8368845: x-IBM930 uses incorrect character for Hex 42 60 Reviewed-by: sherman, rriggs, iris --- make/data/charsetmapping/IBM930.c2b | 5 ----- make/data/charsetmapping/IBM930.map | 10 +--------- test/jdk/sun/nio/cs/mapping/CoderTest.java | 4 ++-- test/jdk/sun/nio/cs/mapping/ConverterTest.java | 5 +++-- test/jdk/sun/nio/cs/mapping/Cp930.b2c | 2 +- test/jdk/sun/nio/cs/mapping/TestConv.java | 4 ++-- 6 files changed, 9 insertions(+), 21 deletions(-) diff --git a/make/data/charsetmapping/IBM930.c2b b/make/data/charsetmapping/IBM930.c2b index 88754763fe3..72107424104 100644 --- a/make/data/charsetmapping/IBM930.c2b +++ b/make/data/charsetmapping/IBM930.c2b @@ -32,11 +32,6 @@ 547d 92ca 53da 9b7e 446e f86f -# -# we should use this one instead of the 4260<-ff0d -#4260 2212 -4260 ff0d -# 426A 00A6 43A1 301C 444A 2014 diff --git a/make/data/charsetmapping/IBM930.map b/make/data/charsetmapping/IBM930.map index 4b9dad9526b..7939e795bdf 100644 --- a/make/data/charsetmapping/IBM930.map +++ b/make/data/charsetmapping/IBM930.map @@ -25,13 +25,6 @@ # 4260 <--> 2212 # 426A <--> 00A6 # -# Warning: -# "our old" implementation seems agree with above "new" mappings -# except the entries 4260 <-> 2212. To keep the "compatbility" -# with the "old" implementation, I changed the entries "temporarily" -# 4260 <-> 2212 -# 4260 <- ff0d -# 00 0000 01 0001 02 0002 @@ -407,8 +400,7 @@ FF 009F 425D FF09 425E FF1B 425F FFE2 -#4260 FF0D -4260 2212 +4260 FF0D 4261 FF0F 426A FFE4 426B FF0C diff --git a/test/jdk/sun/nio/cs/mapping/CoderTest.java b/test/jdk/sun/nio/cs/mapping/CoderTest.java index 05913a40535..2f766736743 100644 --- a/test/jdk/sun/nio/cs/mapping/CoderTest.java +++ b/test/jdk/sun/nio/cs/mapping/CoderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,7 +22,7 @@ */ /* @test - @bug 4691554 6221056 6380723 6404504 6419565 6529796 8301119 + @bug 4691554 6221056 6380723 6404504 6419565 6529796 8301119 8368845 @summary Test the supported New I/O coders @modules jdk.charsets @run main CoderTest diff --git a/test/jdk/sun/nio/cs/mapping/ConverterTest.java b/test/jdk/sun/nio/cs/mapping/ConverterTest.java index be8df03230c..8d33670b0a5 100644 --- a/test/jdk/sun/nio/cs/mapping/ConverterTest.java +++ b/test/jdk/sun/nio/cs/mapping/ConverterTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,8 @@ * @summary test Bug 4199484 * @modules jdk.charsets * @run main ConverterTest - * @bug 4199484 4199599 4199601 4199602 4159519 4201529 4199604 4201532 4947038 6217210 + * @bug 4199484 4199599 4199601 4199602 4159519 4201529 4199604 4201532 4947038 + * 6217210 8368845 */ import java.util.*; diff --git a/test/jdk/sun/nio/cs/mapping/Cp930.b2c b/test/jdk/sun/nio/cs/mapping/Cp930.b2c index 67cc93fd628..3cd45375e2d 100644 --- a/test/jdk/sun/nio/cs/mapping/Cp930.b2c +++ b/test/jdk/sun/nio/cs/mapping/Cp930.b2c @@ -340,7 +340,7 @@ F9 0039 0E425D0F FF09 0E425E0F FF1B 0E425F0F FFE2 -0E42600F 2212 +0E42600F FF0D 0E42610F FF0F 0E426A0F FFE4 0E426B0F FF0C diff --git a/test/jdk/sun/nio/cs/mapping/TestConv.java b/test/jdk/sun/nio/cs/mapping/TestConv.java index 2f4ea424f6c..3bd0b15a7d3 100644 --- a/test/jdk/sun/nio/cs/mapping/TestConv.java +++ b/test/jdk/sun/nio/cs/mapping/TestConv.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,7 +22,7 @@ */ /* @test - @bug 4179153 4652234 6529796 + @bug 4179153 4652234 6529796 8368845 @summary Read code mapping table and check code conversion @modules jdk.charsets */ From 7f070d356c479ae30fe84fcf4d322c0b693fa15a Mon Sep 17 00:00:00 2001 From: Mikael Vidstedt Date: Tue, 7 Oct 2025 17:37:31 +0000 Subject: [PATCH 0095/1639] 8369246: Use https in make/devkit scripts Reviewed-by: ayang, erikj --- make/devkit/Tools.gmk | 10 +++++----- make/devkit/createAutoconfBundle.sh | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/make/devkit/Tools.gmk b/make/devkit/Tools.gmk index 6241674071c..f6ea6749f48 100644 --- a/make/devkit/Tools.gmk +++ b/make/devkit/Tools.gmk @@ -117,13 +117,13 @@ dependencies := gcc binutils ccache mpfr gmp mpc gdb $(foreach dep,$(dependencies),$(eval $(dep)_ver := $(dep)-$($(dep)_ver_only))) -GCC_URL := http://ftp.gnu.org/pub/gnu/gcc/$(gcc_ver)/$(gcc_ver).tar.xz -BINUTILS_URL := http://ftp.gnu.org/pub/gnu/binutils/$(binutils_ver).tar.gz +GCC_URL := https://ftp.gnu.org/pub/gnu/gcc/$(gcc_ver)/$(gcc_ver).tar.xz +BINUTILS_URL := https://ftp.gnu.org/pub/gnu/binutils/$(binutils_ver).tar.gz CCACHE_URL := https://github.com/ccache/ccache/releases/download/v$(ccache_ver_only)/$(ccache_ver).tar.xz MPFR_URL := https://www.mpfr.org/$(mpfr_ver)/$(mpfr_ver).tar.bz2 -GMP_URL := http://ftp.gnu.org/pub/gnu/gmp/$(gmp_ver).tar.bz2 -MPC_URL := http://ftp.gnu.org/pub/gnu/mpc/$(mpc_ver).tar.gz -GDB_URL := http://ftp.gnu.org/gnu/gdb/$(gdb_ver).tar.xz +GMP_URL := https://ftp.gnu.org/pub/gnu/gmp/$(gmp_ver).tar.bz2 +MPC_URL := https://ftp.gnu.org/pub/gnu/mpc/$(mpc_ver).tar.gz +GDB_URL := https://ftp.gnu.org/gnu/gdb/$(gdb_ver).tar.xz REQUIRED_MIN_MAKE_MAJOR_VERSION := 4 ifneq ($(REQUIRED_MIN_MAKE_MAJOR_VERSION),) diff --git a/make/devkit/createAutoconfBundle.sh b/make/devkit/createAutoconfBundle.sh index ebe9c427f76..4697e4eb1e3 100644 --- a/make/devkit/createAutoconfBundle.sh +++ b/make/devkit/createAutoconfBundle.sh @@ -93,7 +93,7 @@ elif test "x$TARGET_PLATFORM" = xlinux_x64; then rpm2cpio $OUTPUT_ROOT/m4-$M4_VERSION.el6.x86_64.rpm | cpio -d -i elif test "x$TARGET_PLATFORM" = xlinux_x86; then M4_VERSION=1.4.13-5 - wget http://yum.oracle.com/repo/OracleLinux/OL6/latest/i386/getPackage/m4-$M4_VERSION.el6.i686.rpm + wget https://yum.oracle.com/repo/OracleLinux/OL6/latest/i386/getPackage/m4-$M4_VERSION.el6.i686.rpm cd $IMAGE_DIR rpm2cpio $OUTPUT_ROOT/m4-$M4_VERSION.el6.i686.rpm | cpio -d -i else From 6bfd018beaf187940ebafc71885045b4aabca673 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Tue, 7 Oct 2025 19:08:22 +0000 Subject: [PATCH 0096/1639] 8366002: Beans.instantiate needs to describe the lookup procedure Reviewed-by: serb, aivanov --- .../share/classes/java/beans/Beans.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/java.desktop/share/classes/java/beans/Beans.java b/src/java.desktop/share/classes/java/beans/Beans.java index 313bfe98515..a95aeb45cbb 100644 --- a/src/java.desktop/share/classes/java/beans/Beans.java +++ b/src/java.desktop/share/classes/java/beans/Beans.java @@ -64,6 +64,22 @@ public class Beans { *

    * Instantiate a JavaBean. *

    + * The bean is created based on a name relative to a class-loader. + * This name should be a {@linkplain ClassLoader##binary-name binary name} of a class such as "a.b.C". + *

    + * The given name can indicate either a serialized object or a class. + * We first try to treat the {@code beanName} as a serialized object + * name then as a class name. + *

    + * When using the {@code beanName} as a serialized object name we convert the + * given {@code beanName} to a resource pathname and add a trailing ".ser" suffix. + * We then try to load a serialized object from that resource. + *

    + * For example, given a {@code beanName} of "x.y", {@code Beans.instantiate} would first + * try to read a serialized object from the resource "x/y.ser" and if + * that failed it would try to load the class "x.y" and create an + * instance of that class. + * * @return a JavaBean * @param cls the class-loader from which we should create * the bean. If this is null, then the system @@ -84,6 +100,22 @@ public class Beans { *

    * Instantiate a JavaBean. *

    + * The bean is created based on a name relative to a class-loader. + * This name should be a {@linkplain ClassLoader##binary-name binary name} of a class such as "a.b.C". + *

    + * The given name can indicate either a serialized object or a class. + * We first try to treat the {@code beanName} as a serialized object + * name then as a class name. + *

    + * When using the {@code beanName} as a serialized object name we convert the + * given {@code beanName} to a resource pathname and add a trailing ".ser" suffix. + * We then try to load a serialized object from that resource. + *

    + * For example, given a {@code beanName} of "x.y", {@code Beans.instantiate} would first + * try to read a serialized object from the resource "x/y.ser" and if + * that failed it would try to load the class "x.y" and create an + * instance of that class. + * * @return a JavaBean * * @param cls the class-loader from which we should create From 910bb68e5191f830ff6f3dff5753e4e5f6214a7b Mon Sep 17 00:00:00 2001 From: Archie Cobbs Date: Tue, 7 Oct 2025 19:32:08 +0000 Subject: [PATCH 0097/1639] 8349847: Support configuring individual lint categories as errors Reviewed-by: vromero --- .../com/sun/tools/javac/code/Lint.java | 29 +---- .../sun/tools/javac/main/JavaCompiler.java | 23 +++- .../com/sun/tools/javac/main/Option.java | 18 +++ .../JavacProcessingEnvironment.java | 2 +- .../tools/javac/resources/javac.properties | 10 +- .../classes/com/sun/tools/javac/util/Log.java | 30 ++++- .../com/sun/tools/javac/util/Options.java | 113 ++++++++++++++---- src/jdk.compiler/share/man/javac.md | 13 +- .../tools/javac/warnings/WerrorLint.e1.out | 4 + .../tools/javac/warnings/WerrorLint.e2.out | 5 + .../tools/javac/warnings/WerrorLint.java | 23 ++++ .../tools/javac/warnings/WerrorLint.w1.out | 2 + .../tools/javac/warnings/WerrorLint.w2.out | 3 + 13 files changed, 214 insertions(+), 61 deletions(-) create mode 100644 test/langtools/tools/javac/warnings/WerrorLint.e1.out create mode 100644 test/langtools/tools/javac/warnings/WerrorLint.e2.out create mode 100644 test/langtools/tools/javac/warnings/WerrorLint.java create mode 100644 test/langtools/tools/javac/warnings/WerrorLint.w1.out create mode 100644 test/langtools/tools/javac/warnings/WerrorLint.w2.out diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java index 88c9da5d9e8..3a8b4e5dbea 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Lint.java @@ -147,33 +147,10 @@ public class Lint { // Process command line options on demand to allow use of root Lint early during startup private void initializeRootIfNeeded() { - - // Already initialized? - if (values != null) - return; - - // Initialize enabled categories based on "-Xlint" flags - if (options.isSet(Option.XLINT) || options.isSet(Option.XLINT_CUSTOM, Option.LINT_CUSTOM_ALL)) { - // If -Xlint or -Xlint:all is given, enable all categories by default - values = EnumSet.allOf(LintCategory.class); - } else if (options.isSet(Option.XLINT_CUSTOM, Option.LINT_CUSTOM_NONE)) { - // if -Xlint:none is given, disable all categories by default - values = LintCategory.newEmptySet(); - } else { - // otherwise, enable on-by-default categories - values = getDefaults(); + if (values == null) { + values = options.getLintCategoriesOf(Option.XLINT, this::getDefaults); + suppressedValues = LintCategory.newEmptySet(); } - - // Look for specific overrides - for (LintCategory lc : LintCategory.values()) { - if (options.isLintExplicitlyEnabled(lc)) { - values.add(lc); - } else if (options.isLintExplicitlyDisabled(lc)) { - values.remove(lc); - } - } - - suppressedValues = LintCategory.newEmptySet(); } // Obtain the set of on-by-default categories. Note that for a few categories, diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java index ee11304dce9..2469dc9e031 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java @@ -31,6 +31,7 @@ import java.nio.file.InvalidPathException; import java.nio.file.ReadOnlyFileSystemException; import java.util.Collection; import java.util.Comparator; +import java.util.EnumSet; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; @@ -55,6 +56,7 @@ import javax.tools.StandardLocation; import com.sun.source.util.TaskEvent; import com.sun.tools.javac.api.MultiTaskListener; import com.sun.tools.javac.code.*; +import com.sun.tools.javac.code.Lint.LintCategory; import com.sun.tools.javac.code.Source.Feature; import com.sun.tools.javac.code.Symbol.ClassSymbol; import com.sun.tools.javac.code.Symbol.CompletionFailure; @@ -440,7 +442,8 @@ public class JavaCompiler { context.get(DiagnosticListener.class) != null; devVerbose = options.isSet("dev"); processPcks = options.isSet("process.packages"); - werror = options.isSet(WERROR); + werrorAny = options.isSet(WERROR) || options.isSet(WERROR_CUSTOM, Option.LINT_CUSTOM_ALL); + werrorLint = options.getLintCategoriesOf(WERROR, LintCategory::newEmptySet); verboseCompilePolicy = options.isSet("verboseCompilePolicy"); @@ -513,9 +516,13 @@ public class JavaCompiler { */ protected boolean processPcks; - /** Switch: treat warnings as errors + /** Switch: treat any kind of warning (lint or non-lint) as an error. */ - protected boolean werror; + protected boolean werrorAny; + + /** Switch: treat lint warnings in the specified {@link LintCategory}s as errors. + */ + protected EnumSet werrorLint; /** Switch: is annotation processing requested explicitly via * CompilationTask.setProcessors? @@ -581,12 +588,20 @@ public class JavaCompiler { */ public int errorCount() { log.reportOutstandingWarnings(); - if (werror && log.nerrors == 0 && log.nwarnings > 0) { + if (log.nerrors == 0 && log.nwarnings > 0 && + (werrorAny || werrorLint.clone().removeAll(log.lintWarnings))) { log.error(Errors.WarningsAndWerror); } return log.nerrors; } + /** + * Should warnings in the given lint category be treated as errors due to a {@code -Werror} flag? + */ + public boolean isWerror(LintCategory lc) { + return werrorAny || werrorLint.contains(lc); + } + protected final Queue stopIfError(CompileState cs, Queue queue) { return shouldStop(cs) ? new ListBuffer() : queue; } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java index 8d5ad4c4d78..c14767a7a8c 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java @@ -563,6 +563,8 @@ public enum Option { // treat warnings as errors WERROR("-Werror", "opt.Werror", STANDARD, BASIC), + WERROR_CUSTOM("-Werror:", "opt.arg.Werror", "opt.Werror.custom", STANDARD, BASIC, ANYOF, getXLintChoices()), + // prompt after each error // new Option("-prompt", "opt.prompt"), PROMPT("-prompt", null, HIDDEN, BASIC), @@ -1132,6 +1134,22 @@ public enum Option { return Option.valueOf(name() + "_CUSTOM"); } + /** + * Like {@link #getCustom} but also requires that the custom option supports lint categories. + * + *

    + * In practice, that means {@code option} must be {@link Option#LINT} or {@link Option#WERROR}. + * + * @param option regular option + * @return corresponding lint custom option + * @throws IllegalArgumentException if no such option exists + */ + public Option getLintCustom() { + if (this == XLINT || this == WERROR) + return getCustom(); + throw new IllegalArgumentException(); + } + public boolean isInBasicOptionGroup() { return group == BASIC; } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java index b28f19bd3af..74d082d4b64 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java @@ -211,7 +211,7 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea } fatalErrors = options.isSet("fatalEnterError"); showResolveErrors = options.isSet("showResolveErrors"); - werror = options.isSet(Option.WERROR); + werror = compiler.isWerror(PROCESSING); fileManager = context.get(JavaFileManager.class); platformAnnotations = initPlatformAnnotations(); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties index 15a63da06eb..6d4276c794b 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties @@ -95,7 +95,13 @@ javac.opt.source=\ Provide source compatibility with the specified Java SE release.\n\ Supported releases: \n {0} javac.opt.Werror=\ - Terminate compilation if warnings occur + Terminate compilation if any warnings occur +javac.opt.arg.Werror=\ + (,)* +javac.opt.Werror.custom=\ + Specify lint categories for which warnings should terminate compilation,\n\ + separated by comma. Precede a key by ''-'' to exclude the specified category.\n\ + Use --help-lint to see the supported keys. javac.opt.A=\ Options to pass to annotation processors javac.opt.implicit=\ @@ -330,7 +336,7 @@ javac.opt.X=\ javac.opt.help=\ Print this help message javac.opt.help.lint=\ - Print the supported keys for -Xlint + Print the supported keys for -Xlint and -Werror javac.opt.help.lint.header=\ The supported keys for -Xlint are: javac.opt.help.lint.enabled.by.default=\ diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Log.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Log.java index 95458f339a1..24a77a751fd 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Log.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Log.java @@ -171,7 +171,7 @@ public class Log extends AbstractLog { lint.isEnabled(category) : // then emit if the category is enabled category.annotationSuppression ? // else emit if the category is not suppressed, where !lint.isSuppressed(category) : // ...suppression happens via @SuppressWarnings - !options.isLintDisabled(category); // ...suppression happens via -Xlint:-category + !options.isDisabled(Option.XLINT, category); // ...suppression happens via -Xlint:-category if (!emit) return; } @@ -553,10 +553,14 @@ public class Log extends AbstractLog { */ public int nerrors = 0; - /** The number of warnings encountered so far. + /** The total number of warnings encountered so far. */ public int nwarnings = 0; + /** Tracks whether any warnings have been encountered in each {@link LintCategory}. + */ + public final EnumSet lintWarnings = LintCategory.newEmptySet(); + /** The number of errors encountered after MaxErrors was reached. */ public int nsuppressederrors = 0; @@ -885,6 +889,7 @@ public class Log extends AbstractLog { public void clear() { recorded.clear(); sourceMap.clear(); + lintWarnings.clear(); nerrors = 0; nwarnings = 0; nsuppressederrors = 0; @@ -940,7 +945,6 @@ public class Log extends AbstractLog { // Strict warnings are always emitted if (diagnostic.isFlagSet(STRICT)) { writeDiagnostic(diagnostic); - nwarnings++; return; } @@ -948,7 +952,6 @@ public class Log extends AbstractLog { if (emitWarnings || diagnostic.isMandatory()) { if (nwarnings < MaxWarnings) { writeDiagnostic(diagnostic); - nwarnings++; } else { nsuppressedwarns++; } @@ -959,7 +962,6 @@ public class Log extends AbstractLog { if (diagnostic.isFlagSet(API) || shouldReport(diagnostic)) { if (nerrors < MaxErrors) { writeDiagnostic(diagnostic); - nerrors++; } else { nsuppressederrors++; } @@ -973,9 +975,25 @@ public class Log extends AbstractLog { } /** - * Write out a diagnostic. + * Write out a diagnostic and bump the warning and error counters as needed. */ protected void writeDiagnostic(JCDiagnostic diag) { + + // Increment counter(s) + switch (diag.getType()) { + case WARNING: + nwarnings++; + Optional.of(diag) + .map(JCDiagnostic::getLintCategory) + .ifPresent(lintWarnings::add); + break; + case ERROR: + nerrors++; + break; + default: + break; + } + if (diagListener != null) { diagListener.report(diag); return; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Options.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Options.java index 32a31028b68..030e5b21758 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Options.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/Options.java @@ -173,66 +173,139 @@ public class Options { /** * Determine if a specific {@link LintCategory} is enabled via a custom - * option flag of the form {@code -Xlint}, {@code -Xlint:all}, or {@code -Xlint:key}. + * option flag of the form {@code -Flag}, {@code -Flag:all}, or {@code -Flag:key}. + * + *

    + * The given {@code option} must have a custom lint variant (available via {@link Option#getLintCustom}). * *

    * Note: It's possible the category was also disabled; this method does not check that. * + * @param option the plain (non-custom) version of the option (e.g., {@link Option#XLINT}) * @param lc the {@link LintCategory} in question - * @return true if {@code lc} has been enabled + * @return true if {@code lc} is enabled via {@code option}'s lint custom variant (e.g., {@link Option#XLINT_CUSTOM}) + * @throws IllegalArgumentException if there is no lint custom variant of {@code option} */ - public boolean isLintEnabled(LintCategory lc) { - return isLintExplicitlyEnabled(lc) || - isSet(Option.XLINT_CUSTOM) || - isSet(Option.XLINT_CUSTOM, Option.LINT_CUSTOM_ALL); + public boolean isEnabled(Option option, LintCategory lc) { + Option custom = option.getLintCustom(); + return isExplicitlyEnabled(option, lc) || isSet(custom) || isSet(custom, Option.LINT_CUSTOM_ALL); } /** * Determine if a specific {@link LintCategory} is disabled via a custom - * option flag of the form {@code -Xlint:none} or {@code -Xlint:-key}. + * option flag of the form {@code -Flag:none} or {@code -Flag:-key}. + * + *

    + * The given {@code option} must have a custom lint variant (available via {@link Option#getLintCustom}). * *

    * Note: It's possible the category was also enabled; this method does not check that. * + * @param option the plain (non-custom) version of the option (e.g., {@link Option#XLINT}) * @param lc the {@link LintCategory} in question - * @return true if {@code lc} has been disabled + * @return true if {@code lc} is disabled via {@code option}'s lint custom variant (e.g., {@link Option#XLINT_CUSTOM}) + * @throws IllegalArgumentException if there is no lint custom variant of {@code option} */ - public boolean isLintDisabled(LintCategory lc) { - return isLintExplicitlyDisabled(lc) || isSet(Option.XLINT_CUSTOM, Option.LINT_CUSTOM_NONE); + public boolean isDisabled(Option option, LintCategory lc) { + return isExplicitlyDisabled(option, lc) || isSet(option.getLintCustom(), Option.LINT_CUSTOM_NONE); } /** * Determine if a specific {@link LintCategory} is explicitly enabled via a custom - * option flag of the form {@code -Xlint:key}. + * option flag of the form {@code -Flag:key}. * *

    - * Note: This does not check for option flags of the form {@code -Xlint} or {@code -Xlint:all}. + * The given {@code option} must have a custom lint variant (available via {@link Option#getLintCustom}). + * + *

    + * Note: This does not check for option flags of the form {@code -Flag} or {@code -Flag:all}. * *

    * Note: It's possible the category was also disabled; this method does not check that. * + * @param option the plain (non-custom) version of the option (e.g., {@link Option#XLINT}) * @param lc the {@link LintCategory} in question - * @return true if {@code lc} has been explicitly enabled + * @return true if {@code lc} is explicitly enabled via {@code option}'s lint custom variant (e.g., {@link Option#XLINT_CUSTOM}) + * @throws IllegalArgumentException if there is no lint custom variant of {@code option} */ - public boolean isLintExplicitlyEnabled(LintCategory lc) { - return lc.optionList.stream().anyMatch(alias -> isSet(Option.XLINT_CUSTOM, alias)); + public boolean isExplicitlyEnabled(Option option, LintCategory lc) { + Option customOption = option.getLintCustom(); + return lc.optionList.stream().anyMatch(alias -> isSet(customOption, alias)); } /** * Determine if a specific {@link LintCategory} is explicitly disabled via a custom - * option flag of the form {@code -Xlint:-key}. + * option flag of the form {@code -Flag:-key}. * *

    - * Note: This does not check for an option flag of the form {@code -Xlint:none}. + * The given {@code option} must have a custom lint variant (available via {@link Option#getLintCustom}). + * + *

    + * Note: This does not check for an option flag of the form {@code -Flag:none}. * *

    * Note: It's possible the category was also enabled; this method does not check that. * + * @param option the plain (non-custom) version of the option (e.g., {@link Option#XLINT}) * @param lc the {@link LintCategory} in question - * @return true if {@code lc} has been explicitly disabled + * @return true if {@code lc} is explicitly disabled via {@code option}'s lint custom variant (e.g., {@link Option#XLINT_CUSTOM}) + * @throws IllegalArgumentException if there is no lint custom variant of {@code option} */ - public boolean isLintExplicitlyDisabled(LintCategory lc) { - return lc.optionList.stream().anyMatch(alias -> isSet(Option.XLINT_CUSTOM, "-" + alias)); + public boolean isExplicitlyDisabled(Option option, LintCategory lc) { + Option customOption = option.getLintCustom(); + return lc.optionList.stream().anyMatch(alias -> isSet(customOption, "-" + alias)); + } + + /** + * Collect the set of {@link LintCategory}s specified by option flag(s) of the form + * {@code -Flag} and/or {@code -Flag:[-]key,[-]key,...}. + * + *

    + * The given {@code option} must have a custom lint variant (available via {@link Option#getLintCustom}). + * + *

    + * The set of categories is calculated as follows. First, an initial set is created: + *

      + *
    • If {@code -Flag} or {@code -Flag:all} appears, the initial set contains all categories; otherwise, + *
    • If {@code -Flag:none} appears, the initial set is empty; otherwise, + *
    • The {@code defaults} parameter is invoked to construct an initial set. + *
    + * Next, for each lint category key {@code key}: + *
      + *
    • If {@code -Flag:key} flag appears, the corresponding category is added to the set; otherwise + *
    • If {@code -Flag:-key} flag appears, the corresponding category is removed to the set + *
    + * Unrecognized {@code key}s are ignored. + * + * @param option the plain (non-custom) version of the option (e.g., {@link Option#XLINT}) + * @param defaults populates the default set, or null for an empty default set + * @return the specified set of categories + * @throws IllegalArgumentException if there is no lint custom variant of {@code option} + */ + public EnumSet getLintCategoriesOf(Option option, Supplier> defaults) { + + // Create the initial set + EnumSet categories; + Option customOption = option.getLintCustom(); + if (isSet(option) || isSet(customOption, Option.LINT_CUSTOM_ALL)) { + categories = EnumSet.allOf(LintCategory.class); + } else if (isSet(customOption, Option.LINT_CUSTOM_NONE)) { + categories = EnumSet.noneOf(LintCategory.class); + } else { + categories = defaults.get(); + } + + // Apply specific overrides + for (LintCategory category : LintCategory.values()) { + if (isExplicitlyEnabled(option, category)) { + categories.add(category); + } else if (isExplicitlyDisabled(option, category)) { + categories.remove(category); + } + } + + // Done + return categories; } public void put(String name, String value) { diff --git a/src/jdk.compiler/share/man/javac.md b/src/jdk.compiler/share/man/javac.md index b8243cc78fb..46246624e53 100644 --- a/src/jdk.compiler/share/man/javac.md +++ b/src/jdk.compiler/share/man/javac.md @@ -1,5 +1,5 @@ --- -# Copyright (c) 1994, 2024, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1994, 2025, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -448,7 +448,16 @@ file system locations may be directories, JAR files or JMOD files. : Prints version information. `-Werror` -: Terminates compilation when warnings occur. +: Terminates compilation when any warnings occur; this includes warnings in all lint + categories, as well as non-lint warnings. + +`-Werror:`\[`-`\]*key*(`,`\[`-`\]*key*)\* +: Specify lint categories for which warnings should terminate compilation. The keys + `all` and `none` include or exclude all categories (respectively); other keys include + the corresponding category, or exclude it if preceded by a hyphen (`-`). By default, + no categories are included. In order to terminate compilation, the category must also + be enabled (via [`-Xlint`](#option-Xlint-custom), if necessary). + See [`-Xlint`](#option-Xlint-custom) below for the list of lint category keys. ### Extra Options diff --git a/test/langtools/tools/javac/warnings/WerrorLint.e1.out b/test/langtools/tools/javac/warnings/WerrorLint.e1.out new file mode 100644 index 00000000000..ae99cfa5056 --- /dev/null +++ b/test/langtools/tools/javac/warnings/WerrorLint.e1.out @@ -0,0 +1,4 @@ +WerrorLint.java:20:19: compiler.warn.strictfp +- compiler.err.warnings.and.werror +1 error +1 warning diff --git a/test/langtools/tools/javac/warnings/WerrorLint.e2.out b/test/langtools/tools/javac/warnings/WerrorLint.e2.out new file mode 100644 index 00000000000..1c9bd4d54f8 --- /dev/null +++ b/test/langtools/tools/javac/warnings/WerrorLint.e2.out @@ -0,0 +1,5 @@ +WerrorLint.java:20:19: compiler.warn.strictfp +WerrorLint.java:21:30: compiler.warn.empty.if +- compiler.err.warnings.and.werror +1 error +2 warnings diff --git a/test/langtools/tools/javac/warnings/WerrorLint.java b/test/langtools/tools/javac/warnings/WerrorLint.java new file mode 100644 index 00000000000..3331a664d55 --- /dev/null +++ b/test/langtools/tools/javac/warnings/WerrorLint.java @@ -0,0 +1,23 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8349847 + * + * @compile -XDrawDiagnostics -Xlint:none WerrorLint.java + * @compile -XDrawDiagnostics -Xlint:none -Werror WerrorLint.java + * @compile -XDrawDiagnostics -Xlint:none -Werror:empty WerrorLint.java + * @compile -XDrawDiagnostics -Xlint:none -Werror:strictfp WerrorLint.java + * @compile/ref=WerrorLint.w2.out -XDrawDiagnostics -Xlint:all WerrorLint.java + * @compile/fail/ref=WerrorLint.e2.out -XDrawDiagnostics -Xlint:all -Werror WerrorLint.java + * @compile/fail/ref=WerrorLint.e2.out -XDrawDiagnostics -Xlint:all -Werror:empty WerrorLint.java + * @compile/fail/ref=WerrorLint.e2.out -XDrawDiagnostics -Xlint:all -Werror:strictfp WerrorLint.java + * @compile/ref=WerrorLint.w1.out -XDrawDiagnostics WerrorLint.java + * @compile/fail/ref=WerrorLint.e1.out -XDrawDiagnostics -Werror WerrorLint.java + * @compile/ref=WerrorLint.w1.out -XDrawDiagnostics -Werror:empty WerrorLint.java + * @compile/fail/ref=WerrorLint.e1.out -XDrawDiagnostics -Werror:strictfp WerrorLint.java + */ + +class WerrorLint { + strictfp void m() { // [strictfp] - this category is enabled by default + if (hashCode() == 1) ; // [empty] - this category is disabled by default + } +} diff --git a/test/langtools/tools/javac/warnings/WerrorLint.w1.out b/test/langtools/tools/javac/warnings/WerrorLint.w1.out new file mode 100644 index 00000000000..3e19de51033 --- /dev/null +++ b/test/langtools/tools/javac/warnings/WerrorLint.w1.out @@ -0,0 +1,2 @@ +WerrorLint.java:20:19: compiler.warn.strictfp +1 warning diff --git a/test/langtools/tools/javac/warnings/WerrorLint.w2.out b/test/langtools/tools/javac/warnings/WerrorLint.w2.out new file mode 100644 index 00000000000..bac258706a6 --- /dev/null +++ b/test/langtools/tools/javac/warnings/WerrorLint.w2.out @@ -0,0 +1,3 @@ +WerrorLint.java:20:19: compiler.warn.strictfp +WerrorLint.java:21:30: compiler.warn.empty.if +2 warnings From 4ee6079b11034e7de8be72cd2832fb717c2f140d Mon Sep 17 00:00:00 2001 From: Mikael Vidstedt Date: Wed, 8 Oct 2025 02:05:20 +0000 Subject: [PATCH 0098/1639] 8369328: Use uppercase variable names in the devkit makefiles Reviewed-by: erikj --- make/devkit/Makefile | 50 +++++++-------- make/devkit/Tools.gmk | 146 +++++++++++++++++++++--------------------- 2 files changed, 98 insertions(+), 98 deletions(-) diff --git a/make/devkit/Makefile b/make/devkit/Makefile index ffa23508a13..30e0dce0839 100644 --- a/make/devkit/Makefile +++ b/make/devkit/Makefile @@ -57,61 +57,61 @@ COMMA := , -os := $(shell uname -o) -cpu := $(shell uname -m) +OS := $(shell uname -o) +CPU := $(shell uname -m) # Figure out what platform this is building on. -me := $(cpu)-$(if $(findstring Linux,$(os)),linux-gnu) +ME := $(CPU)-$(if $(findstring Linux,$(OS)),linux-gnu) -$(info Building on platform $(me)) +$(info Building on platform $(ME)) # # By default just build for the current platform, which is assumed to be Linux # ifeq ($(TARGETS), ) - platforms := $(me) - host_platforms := $(platforms) + PLATFORMS := $(ME) + HOST_PLATFORMS := $(PLATFORMS) else - platforms := $(subst $(COMMA), , $(TARGETS)) - host_platforms := $(me) + PLATFORMS := $(subst $(COMMA), , $(TARGETS)) + HOST_PLATFORMS := $(ME) endif -target_platforms := $(platforms) -$(info host_platforms $(host_platforms)) -$(info target_platforms $(target_platforms)) +TARGET_PLATFORMS := $(PLATFORMS) +$(info HOST_PLATFORMS $(HOST_PLATFORMS)) +$(info TARGET_PLATFORMS $(TARGET_PLATFORMS)) -all compile : $(platforms) +all compile : $(PLATFORMS) ifeq ($(SKIP_ME), ) - $(foreach p,$(filter-out $(me),$(platforms)),$(eval $(p) : $$(me))) + $(foreach p,$(filter-out $(ME),$(PLATFORMS)),$(eval $(p) : $$(ME))) endif OUTPUT_ROOT = $(abspath ../../build/devkit) RESULT = $(OUTPUT_ROOT)/result -submakevars = HOST=$@ BUILD=$(me) RESULT=$(RESULT) OUTPUT_ROOT=$(OUTPUT_ROOT) +SUBMAKEVARS = HOST=$@ BUILD=$(ME) RESULT=$(RESULT) OUTPUT_ROOT=$(OUTPUT_ROOT) -$(host_platforms) : +$(HOST_PLATFORMS) : @echo 'Building compilers for $@' - @echo 'Targets: $(target_platforms)' - for p in $(filter $@, $(target_platforms)) $(filter-out $@, $(target_platforms)); do \ - $(MAKE) -f Tools.gmk download-rpms $(submakevars) \ + @echo 'Targets: $(TARGET_PLATFORMS)' + for p in $(filter $@, $(TARGET_PLATFORMS)) $(filter-out $@, $(TARGET_PLATFORMS)); do \ + $(MAKE) -f Tools.gmk download-rpms $(SUBMAKEVARS) \ TARGET=$$p PREFIX=$(RESULT)/$@-to-$$p && \ - $(MAKE) -f Tools.gmk all $(submakevars) \ + $(MAKE) -f Tools.gmk all $(SUBMAKEVARS) \ TARGET=$$p PREFIX=$(RESULT)/$@-to-$$p && \ - $(MAKE) -f Tools.gmk ccache $(submakevars) \ + $(MAKE) -f Tools.gmk ccache $(SUBMAKEVARS) \ TARGET=$@ PREFIX=$(RESULT)/$@-to-$$p || exit 1 ; \ done @echo 'All done"' -today := $(shell date +%Y%m%d) +TODAY := $(shell date +%Y%m%d) define Mktar - $(1)-to-$(2)_tar = $$(RESULT)/sdk-$(1)-to-$(2)-$$(today).tar.gz + $(1)-to-$(2)_tar = $$(RESULT)/sdk-$(1)-to-$(2)-$$(TODAY).tar.gz $$($(1)-to-$(2)_tar) : PLATFORM = $(1)-to-$(2) TARFILES += $$($(1)-to-$(2)_tar) endef -$(foreach p,$(host_platforms),$(foreach t,$(target_platforms),$(eval $(call Mktar,$(p),$(t))))) +$(foreach p,$(HOST_PLATFORMS),$(foreach t,$(TARGET_PLATFORMS),$(eval $(call Mktar,$(p),$(t))))) tars : all $(TARFILES) onlytars : $(TARFILES) @@ -119,9 +119,9 @@ onlytars : $(TARFILES) $(MAKE) -r -f Tars.gmk SRC_DIR=$(RESULT)/$(PLATFORM) TAR_FILE=$@ clean : - rm -rf $(addprefix ../../build/devkit/, result $(host_platforms)) + rm -rf $(addprefix ../../build/devkit/, result $(HOST_PLATFORMS)) dist-clean: clean rm -rf $(addprefix ../../build/devkit/, src download) FORCE : -.PHONY : all compile tars $(configs) $(host_platforms) clean dist-clean +.PHONY : all compile tars $(HOST_PLATFORMS) clean dist-clean diff --git a/make/devkit/Tools.gmk b/make/devkit/Tools.gmk index f6ea6749f48..77a201d0c38 100644 --- a/make/devkit/Tools.gmk +++ b/make/devkit/Tools.gmk @@ -39,7 +39,7 @@ # Fix this... # -uppercase = $(shell echo $1 | tr a-z A-Z) +lowercase = $(shell echo $1 | tr A-Z a-z) $(info TARGET=$(TARGET)) $(info HOST=$(HOST)) @@ -104,26 +104,26 @@ endif ################################################################################ # Define external dependencies -gcc_ver_only := 14.2.0 -binutils_ver_only := 2.43 -ccache_ver_only := 4.10.2 +GCC_VER_ONLY := 14.2.0 +BINUTILS_VER_ONLY := 2.43 +CCACHE_VER_ONLY := 4.10.2 CCACHE_CMAKE_BASED := 1 -mpfr_ver_only := 4.2.1 -gmp_ver_only := 6.3.0 -mpc_ver_only := 1.3.1 -gdb_ver_only := 15.2 +MPFR_VER_ONLY := 4.2.1 +GMP_VER_ONLY := 6.3.0 +MPC_VER_ONLY := 1.3.1 +GDB_VER_ONLY := 15.2 -dependencies := gcc binutils ccache mpfr gmp mpc gdb +DEPENDENCIES := GCC BINUTILS CCACHE MPFR GMP MPC GDB -$(foreach dep,$(dependencies),$(eval $(dep)_ver := $(dep)-$($(dep)_ver_only))) +$(foreach dep,$(DEPENDENCIES),$(eval $(dep)_VER := $(call lowercase,$(dep)-$($(dep)_VER_ONLY)))) -GCC_URL := https://ftp.gnu.org/pub/gnu/gcc/$(gcc_ver)/$(gcc_ver).tar.xz -BINUTILS_URL := https://ftp.gnu.org/pub/gnu/binutils/$(binutils_ver).tar.gz -CCACHE_URL := https://github.com/ccache/ccache/releases/download/v$(ccache_ver_only)/$(ccache_ver).tar.xz -MPFR_URL := https://www.mpfr.org/$(mpfr_ver)/$(mpfr_ver).tar.bz2 -GMP_URL := https://ftp.gnu.org/pub/gnu/gmp/$(gmp_ver).tar.bz2 -MPC_URL := https://ftp.gnu.org/pub/gnu/mpc/$(mpc_ver).tar.gz -GDB_URL := https://ftp.gnu.org/gnu/gdb/$(gdb_ver).tar.xz +GCC_URL := https://ftp.gnu.org/pub/gnu/gcc/$(GCC_VER)/$(GCC_VER).tar.xz +BINUTILS_URL := https://ftp.gnu.org/pub/gnu/binutils/$(BINUTILS_VER).tar.gz +CCACHE_URL := https://github.com/ccache/ccache/releases/download/v$(CCACHE_VER_ONLY)/$(CCACHE_VER).tar.xz +MPFR_URL := https://www.mpfr.org/$(MPFR_VER)/$(MPFR_VER).tar.bz2 +GMP_URL := https://ftp.gnu.org/pub/gnu/gmp/$(GMP_VER).tar.bz2 +MPC_URL := https://ftp.gnu.org/pub/gnu/mpc/$(MPC_VER).tar.gz +GDB_URL := https://ftp.gnu.org/gnu/gdb/$(GDB_VER).tar.xz REQUIRED_MIN_MAKE_MAJOR_VERSION := 4 ifneq ($(REQUIRED_MIN_MAKE_MAJOR_VERSION),) @@ -180,10 +180,10 @@ DOWNLOAD_RPMS := $(DOWNLOAD)/rpms/$(TARGET)-$(LINUX_VERSION) SRCDIR := $(OUTPUT_ROOT)/src # Marker file for unpacking rpms -rpms := $(SYSROOT)/rpms_unpacked +RPMS := $(SYSROOT)/rpms_unpacked # Need to patch libs that are linker scripts to use non-absolute paths -libs := $(SYSROOT)/libs_patched +LIBS := $(SYSROOT)/libs_patched ################################################################################ # Download RPMs @@ -228,7 +228,7 @@ define Download endef # Download and unpack all source packages -$(foreach dep,$(dependencies),$(eval $(call Download,$(call uppercase,$(dep))))) +$(foreach dep,$(DEPENDENCIES),$(eval $(call Download,$(dep)))) ################################################################################ # Unpack RPMS @@ -250,7 +250,7 @@ RPM_FILE_LIST := $(sort $(foreach a, $(RPM_ARCHS), \ # Note. For building linux you should install rpm2cpio. define unrpm $(SYSROOT)/$(notdir $(1)).unpacked : $(1) - $$(rpms) : $(SYSROOT)/$(notdir $(1)).unpacked + $$(RPMS) : $(SYSROOT)/$(notdir $(1)).unpacked endef %.unpacked : @@ -277,7 +277,7 @@ $(foreach p,$(RPM_FILE_LIST),$(eval $(call unrpm,$(p)))) # have it anyway, but just to make sure... # Patch libc.so and libpthread.so to force linking against libraries in sysroot # and not the ones installed on the build machine. -$(libs) : $(rpms) +$(LIBS) : $(RPMS) @echo Patching libc and pthreads @(for f in `find $(SYSROOT) -name libc.so -o -name libpthread.so`; do \ (cat $$f | sed -e 's|/usr/lib64/||g' \ @@ -293,10 +293,10 @@ $(libs) : $(rpms) # Create links for ffi header files so that they become visible by default when using the # devkit. ifeq ($(ARCH), x86_64) - $(SYSROOT)/usr/include/ffi.h: $(rpms) + $(SYSROOT)/usr/include/ffi.h: $(RPMS) cd $(@D) && rm -f $(@F) && ln -s ../lib/libffi-*/include/$(@F) . - $(SYSROOT)/usr/include/ffitarget.h: $(rpms) + $(SYSROOT)/usr/include/ffitarget.h: $(RPMS) cd $(@D) && rm -f $(@F) && ln -s ../lib/libffi-*/include/$(@F) . SYSROOT_LINKS += $(SYSROOT)/usr/include/ffi.h $(SYSROOT)/usr/include/ffitarget.h @@ -305,7 +305,7 @@ endif ################################################################################ # Define marker files for each source package to be compiled -$(foreach dep,$(dependencies),$(eval $(dep) = $(TARGETDIR)/$($(dep)_ver).done)) +$(foreach dep,$(DEPENDENCIES),$(eval $(dep) = $(TARGETDIR)/$($(dep)_VER).done)) ################################################################################ @@ -345,48 +345,48 @@ TOOLS ?= $(call declare_tools,_FOR_TARGET,$(TARGET)-) # CFLAG_ to most likely -m32. define mk_bfd $$(info Libs for $(1)) - $$(BUILDDIR)/$$(binutils_ver)-$(subst /,-,$(1))/Makefile \ + $$(BUILDDIR)/$$(BINUTILS_VER)-$(subst /,-,$(1))/Makefile \ : CFLAGS += $$(CFLAGS_$(1)) - $$(BUILDDIR)/$$(binutils_ver)-$(subst /,-,$(1))/Makefile \ + $$(BUILDDIR)/$$(BINUTILS_VER)-$(subst /,-,$(1))/Makefile \ : LIBDIRS = --libdir=$(TARGETDIR)/$(1) - bfdlib += $$(TARGETDIR)/$$(binutils_ver)-$(subst /,-,$(1)).done - bfdmakes += $$(BUILDDIR)/$$(binutils_ver)-$(subst /,-,$(1))/Makefile + BFDLIB += $$(TARGETDIR)/$$(BINUTILS_VER)-$(subst /,-,$(1)).done + BFDMAKES += $$(BUILDDIR)/$$(BINUTILS_VER)-$(subst /,-,$(1))/Makefile endef # Create one set of bfds etc for each multilib arch $(foreach l,$(LIBDIRS),$(eval $(call mk_bfd,$(l)))) # Only build these two libs. -$(bfdlib) : MAKECMD = all-libiberty all-bfd -$(bfdlib) : INSTALLCMD = install-libiberty install-bfd +$(BFDLIB) : MAKECMD = all-libiberty all-bfd +$(BFDLIB) : INSTALLCMD = install-libiberty install-bfd # Building targets libbfd + libiberty. HOST==TARGET, i.e not # for a cross env. -$(bfdmakes) : CONFIG = --target=$(TARGET) \ +$(BFDMAKES) : CONFIG = --target=$(TARGET) \ --host=$(TARGET) --build=$(BUILD) \ --prefix=$(TARGETDIR) \ --with-sysroot=$(SYSROOT) \ $(LIBDIRS) -$(bfdmakes) : TOOLS = $(call declare_tools,_FOR_TARGET,$(TARGET)-) $(call declare_tools,,$(TARGET)-) +$(BFDMAKES) : TOOLS = $(call declare_tools,_FOR_TARGET,$(TARGET)-) $(call declare_tools,,$(TARGET)-) ################################################################################ -$(gcc) \ - $(binutils) \ - $(gmp) \ - $(mpfr) \ - $(mpc) \ - $(bfdmakes) \ - $(ccache) : ENVS += $(TOOLS) +$(GCC) \ + $(BINUTILS) \ + $(GMP) \ + $(MPFR) \ + $(MPC) \ + $(BFDMAKES) \ + $(CCACHE) : ENVS += $(TOOLS) # libdir to work around hateful bfd stuff installing into wrong dirs... # ensure we have 64 bit bfd support in the HOST library. I.e our # compiler on i686 will know 64 bit symbols, BUT later # we build just the libs again for TARGET, then with whatever the arch # wants. -$(BUILDDIR)/$(binutils_ver)/Makefile : CONFIG += --enable-64-bit-bfd --libdir=$(PREFIX)/$(word 1,$(LIBDIRS)) +$(BUILDDIR)/$(BINUTILS_VER)/Makefile : CONFIG += --enable-64-bit-bfd --libdir=$(PREFIX)/$(word 1,$(LIBDIRS)) ifeq ($(filter $(ARCH), s390x riscv64 ppc64le), ) # gold compiles but cannot link properly on s390x @ gcc 13.2 and Fedore 41 @@ -397,8 +397,8 @@ endif # Makefile creation. Simply run configure in build dir. # Setting CFLAGS to -O2 generates a much faster ld. -$(bfdmakes) \ -$(BUILDDIR)/$(binutils_ver)/Makefile \ +$(BFDMAKES) \ +$(BUILDDIR)/$(BINUTILS_VER)/Makefile \ : $(BINUTILS_CFG) $(info Configuring $@. Log in $(@D)/log.config) @mkdir -p $(@D) @@ -417,7 +417,7 @@ $(BUILDDIR)/$(binutils_ver)/Makefile \ ) > $(@D)/log.config 2>&1 @echo 'done' -$(BUILDDIR)/$(mpfr_ver)/Makefile \ +$(BUILDDIR)/$(MPFR_VER)/Makefile \ : $(MPFR_CFG) $(info Configuring $@. Log in $(@D)/log.config) @mkdir -p $(@D) @@ -432,7 +432,7 @@ $(BUILDDIR)/$(mpfr_ver)/Makefile \ ) > $(@D)/log.config 2>&1 @echo 'done' -$(BUILDDIR)/$(gmp_ver)/Makefile \ +$(BUILDDIR)/$(GMP_VER)/Makefile \ : $(GMP_CFG) $(info Configuring $@. Log in $(@D)/log.config) @mkdir -p $(@D) @@ -449,7 +449,7 @@ $(BUILDDIR)/$(gmp_ver)/Makefile \ ) > $(@D)/log.config 2>&1 @echo 'done' -$(BUILDDIR)/$(mpc_ver)/Makefile \ +$(BUILDDIR)/$(MPC_VER)/Makefile \ : $(MPC_CFG) $(info Configuring $@. Log in $(@D)/log.config) @mkdir -p $(@D) @@ -468,11 +468,11 @@ $(BUILDDIR)/$(mpc_ver)/Makefile \ # Only valid if glibc target -> linux # proper destructor handling for c++ ifneq (,$(findstring linux,$(TARGET))) - $(BUILDDIR)/$(gcc_ver)/Makefile : CONFIG += --enable-__cxa_atexit + $(BUILDDIR)/$(GCC_VER)/Makefile : CONFIG += --enable-__cxa_atexit endif ifeq ($(ARCH), armhfp) - $(BUILDDIR)/$(gcc_ver)/Makefile : CONFIG += --with-float=hard + $(BUILDDIR)/$(GCC_VER)/Makefile : CONFIG += --with-float=hard endif ifneq ($(filter riscv64 ppc64le s390x, $(ARCH)), ) @@ -487,7 +487,7 @@ endif # skip native language. # and link and assemble with the binutils we created # earlier, so --with-gnu* -$(BUILDDIR)/$(gcc_ver)/Makefile \ +$(BUILDDIR)/$(GCC_VER)/Makefile \ : $(GCC_CFG) $(info Configuring $@. Log in $(@D)/log.config) mkdir -p $(@D) @@ -509,17 +509,17 @@ $(BUILDDIR)/$(gcc_ver)/Makefile \ @echo 'done' # need binutils for gcc -$(gcc) : $(binutils) +$(GCC) : $(BINUTILS) # as of 4.3 or so need these for doing config -$(BUILDDIR)/$(gcc_ver)/Makefile : $(gmp) $(mpfr) $(mpc) -$(mpfr) : $(gmp) -$(mpc) : $(gmp) $(mpfr) +$(BUILDDIR)/$(GCC_VER)/Makefile : $(GMP) $(MPFR) $(MPC) +$(MPFR) : $(GMP) +$(MPC) : $(GMP) $(MPFR) ################################################################################ # Build gdb but only where host and target match ifeq ($(HOST), $(TARGET)) - $(BUILDDIR)/$(gdb_ver)/Makefile: $(GDB_CFG) + $(BUILDDIR)/$(GDB_VER)/Makefile: $(GDB_CFG) $(info Configuring $@. Log in $(@D)/log.config) mkdir -p $(@D) ( \ @@ -532,9 +532,9 @@ ifeq ($(HOST), $(TARGET)) ) > $(@D)/log.config 2>&1 @echo 'done' - $(gdb): $(gcc) + $(GDB): $(GCC) else - $(BUILDDIR)/$(gdb_ver)/Makefile: + $(BUILDDIR)/$(GDB_VER)/Makefile: $(info Faking $@, not used when cross-compiling) mkdir -p $(@D) echo "install:" > $@ @@ -543,7 +543,7 @@ endif ################################################################################ # very straightforward. just build a ccache. it is only for host. -$(BUILDDIR)/$(ccache_ver)/Makefile \ +$(BUILDDIR)/$(CCACHE_VER)/Makefile \ : $(CCACHE_SRC_MARKER) $(info Configuring $@. Log in $(@D)/log.config) @mkdir -p $(@D) @@ -554,12 +554,12 @@ $(BUILDDIR)/$(ccache_ver)/Makefile \ ) > $(@D)/log.config 2>&1 @echo 'done' -gccpatch = $(TARGETDIR)/gcc-patched +GCC_PATCHED = $(TARGETDIR)/gcc-patched ################################################################################ # For some reason cpp is not created as a target-compiler ifeq ($(HOST),$(TARGET)) - $(gccpatch) : $(gcc) link_libs + $(GCC_PATCHED) : $(GCC) link_libs @echo -n 'Creating compiler symlinks...' @for f in cpp; do \ if [ ! -e $(PREFIX)/bin/$(TARGET)-$$f ]; \ @@ -587,7 +587,7 @@ ifeq ($(HOST),$(TARGET)) done;) @echo 'done' else - $(gccpatch) : + $(GCC_PATCHED) : @echo 'done' endif @@ -615,7 +615,7 @@ $(PREFIX)/devkit.info: echo '# This file describes to configure how to interpret the contents of this' >> $@ echo '# devkit' >> $@ echo '' >> $@ - echo 'DEVKIT_NAME="$(gcc_ver) - $(LINUX_VERSION)"' >> $@ + echo 'DEVKIT_NAME="$(GCC_VER) - $(LINUX_VERSION)"' >> $@ echo 'DEVKIT_TOOLCHAIN_PATH="$$DEVKIT_ROOT/bin"' >> $@ echo 'DEVKIT_SYSROOT="$$DEVKIT_ROOT/$(TARGET)/sysroot"' >> $@ echo 'DEVKIT_EXTRA_PATH="$$DEVKIT_ROOT/bin"' >> $@ @@ -651,32 +651,32 @@ ifeq ($(TARGET), $(HOST)) @echo 'Creating missing $* soft link' ln -s $(TARGET)-$* $@ - missing-links := $(addprefix $(PREFIX)/bin/, \ - addr2line ar as c++ c++filt dwp elfedit g++ gcc gcc-$(gcc_ver_only) gprof ld ld.bfd \ + MISSING_LINKS := $(addprefix $(PREFIX)/bin/, \ + addr2line ar as c++ c++filt dwp elfedit g++ gcc gcc-$(GCC_VER_ONLY) gprof ld ld.bfd \ ld.gold nm objcopy objdump ranlib readelf size strings strip) endif # Add link to work around "plugin needed to handle lto object" (JDK-8344272) -$(PREFIX)/lib/bfd-plugins/liblto_plugin.so: $(PREFIX)/libexec/gcc/$(TARGET)/$(gcc_ver_only)/liblto_plugin.so +$(PREFIX)/lib/bfd-plugins/liblto_plugin.so: $(PREFIX)/libexec/gcc/$(TARGET)/$(GCC_VER_ONLY)/liblto_plugin.so @echo 'Creating missing $(@F) soft link' @mkdir -p $(@D) ln -s $$(realpath -s --relative-to=$(@D) $<) $@ -missing-links += $(PREFIX)/lib/bfd-plugins/liblto_plugin.so +MISSING_LINKS += $(PREFIX)/lib/bfd-plugins/liblto_plugin.so ################################################################################ -bfdlib : $(bfdlib) -binutils : $(binutils) -rpms : $(rpms) -libs : $(libs) +bfdlib : $(BFDLIB) +binutils : $(BINUTILS) +rpms : $(RPMS) +libs : $(LIBS) sysroot : rpms libs -gcc : sysroot $(gcc) $(gccpatch) -gdb : $(gdb) -all : binutils gcc bfdlib $(PREFIX)/devkit.info $(missing-links) $(SYSROOT_LINKS) \ +gcc : sysroot $(GCC) $(GCC_PATCHED) +gdb : $(GDB) +all : binutils gcc bfdlib $(PREFIX)/devkit.info $(MISSING_LINKS) $(SYSROOT_LINKS) \ $(THESE_MAKEFILES) gdb # this is only built for host. so separate. -ccache : $(ccache) +ccache : $(CCACHE) .PHONY : gcc all binutils bfdlib link_libs rpms libs sysroot From 650fd35b3b30bf16e8caad968bd335d423c87b7d Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Wed, 8 Oct 2025 03:00:30 +0000 Subject: [PATCH 0099/1639] 8335646: Nimbus : JLabel not painted with LAF defined foreground color on Ubuntu 24.04 Reviewed-by: aivanov, dnguyen, serb --- test/jdk/javax/swing/plaf/basic/BasicHTML/bug4248210.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/jdk/javax/swing/plaf/basic/BasicHTML/bug4248210.java b/test/jdk/javax/swing/plaf/basic/BasicHTML/bug4248210.java index fddfbb28384..54f7744ee90 100644 --- a/test/jdk/javax/swing/plaf/basic/BasicHTML/bug4248210.java +++ b/test/jdk/javax/swing/plaf/basic/BasicHTML/bug4248210.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,7 +71,7 @@ public class bug4248210 { UIManager.getDefaults().put("Label.foreground", labelColor); } - JLabel label = new JLabel("Can You Read This?"); + JLabel label = new JLabel("\u2588 \u2588 \u2588 \u2588"); label.setSize(150, 30); BufferedImage img = paintToImage(label); From 2ac24bf1bac9c32704ebd72b93a75819b9404063 Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Wed, 8 Oct 2025 03:06:29 +0000 Subject: [PATCH 0100/1639] 8367389: C2 SuperWord: refactor VTransform to model the whole loop instead of just the basic block Reviewed-by: roland, mhaessig --- src/hotspot/share/opto/phasetype.hpp | 7 +- src/hotspot/share/opto/superword.cpp | 220 +++++------------- src/hotspot/share/opto/superword.hpp | 6 +- .../share/opto/superwordVTransformBuilder.cpp | 60 +++-- .../share/opto/superwordVTransformBuilder.hpp | 2 + src/hotspot/share/opto/vectorization.cpp | 74 +++++- src/hotspot/share/opto/vectorization.hpp | 102 +++++--- src/hotspot/share/opto/vtransform.cpp | 149 ++++++++---- src/hotspot/share/opto/vtransform.hpp | 147 +++++++----- .../lib/ir_framework/CompilePhase.java | 6 +- 10 files changed, 447 insertions(+), 326 deletions(-) diff --git a/src/hotspot/share/opto/phasetype.hpp b/src/hotspot/share/opto/phasetype.hpp index 5c733c7dc0a..f24938b51c1 100644 --- a/src/hotspot/share/opto/phasetype.hpp +++ b/src/hotspot/share/opto/phasetype.hpp @@ -89,10 +89,9 @@ flags(PHASEIDEALLOOP2, "PhaseIdealLoop 2") \ flags(PHASEIDEALLOOP3, "PhaseIdealLoop 3") \ flags(AUTO_VECTORIZATION1_BEFORE_APPLY, "AutoVectorization 1, before Apply") \ - flags(AUTO_VECTORIZATION2_AFTER_REORDER, "AutoVectorization 2, after Apply Memop Reordering") \ - flags(AUTO_VECTORIZATION3_AFTER_ADJUST_LIMIT, "AutoVectorization 3, after Adjusting Pre-loop Limit") \ - flags(AUTO_VECTORIZATION4_AFTER_SPECULATIVE_RUNTIME_CHECKS, "AutoVectorization 4, after Adding Speculative Runtime Checks") \ - flags(AUTO_VECTORIZATION5_AFTER_APPLY, "AutoVectorization 5, after Apply") \ + flags(AUTO_VECTORIZATION3_AFTER_ADJUST_LIMIT, "AutoVectorization 2, after Adjusting Pre-loop Limit") \ + flags(AUTO_VECTORIZATION4_AFTER_SPECULATIVE_RUNTIME_CHECKS, "AutoVectorization 3, after Adding Speculative Runtime Checks") \ + flags(AUTO_VECTORIZATION5_AFTER_APPLY, "AutoVectorization 4, after Apply") \ flags(BEFORE_CCP1, "Before PhaseCCP 1") \ flags(CCP1, "PhaseCCP 1") \ flags(ITER_GVN2, "Iter GVN 2") \ diff --git a/src/hotspot/share/opto/superword.cpp b/src/hotspot/share/opto/superword.cpp index 2b3928781b8..41a4339e4c9 100644 --- a/src/hotspot/share/opto/superword.cpp +++ b/src/hotspot/share/opto/superword.cpp @@ -40,7 +40,7 @@ SuperWord::SuperWord(const VLoopAnalyzer &vloop_analyzer) : NOT_PRODUCT(COMMA is_trace_superword_packset()) NOT_PRODUCT(COMMA is_trace_superword_rejections()) ), - _mem_ref_for_main_loop_alignment(nullptr), + _vpointer_for_main_loop_alignment(nullptr), _aw_for_main_loop_alignment(0), _do_vector_loop(phase()->C->do_vector_loop()), // whether to do vectorization/simd style _num_work_vecs(0), // amount of vector work we have @@ -455,11 +455,16 @@ bool SuperWord::transform_loop() { // // 8) The pairs are combined into vector sized packs. // -// 9) Reorder the memory slices to co-locate members of the memory packs. +// 9) The packs are split and filtered, to ensure correctness and that +// all packs have corresponding vector nodes implemented in the backend. // -// 10) Generate ideal vector nodes for the final set of packs and where necessary, -// inserting scalar promotion, vector creation from multiple scalars, and -// extraction of scalar values from vectors. +// 10) VTransform (see vtransform.hpp) +// - construct from PackSet +// - schedule (detect circles) +// - apply +// - align main loop +// - add runtime checks (aliasing and alignment) +// - build new loop with vector C2 nodes // // Runtime Checks: // Some required properties cannot be proven statically, and require a @@ -498,7 +503,7 @@ bool SuperWord::SLP_extract() { DEBUG_ONLY(verify_packs();) DEBUG_ONLY(verify_no_extract()); - return schedule_and_apply(); + return do_vtransform(); } int SuperWord::MemOp::cmp_by_group(MemOp* a, MemOp* b) { @@ -660,39 +665,9 @@ void SuperWord::create_adjacent_memop_pairs_in_one_group(const GrowableArrayfast_outs(imax); i < imax; i++) { - PhiNode* phi = cl->fast_out(i)->isa_Phi(); - if (phi != nullptr && _vloop.in_bb(phi) && phi->is_memory_phi()) { - Node* phi_tail = phi->in(LoopNode::LoopBackControl); - if (phi_tail != phi->in(LoopNode::EntryControl)) { - _heads.push(phi); - _tails.push(phi_tail->as_Mem()); - } - } - } - - NOT_PRODUCT( if (_vloop.is_trace_memory_slices()) { print(); } ) -} - -#ifndef PRODUCT -void VLoopMemorySlices::print() const { - tty->print_cr("\nVLoopMemorySlices::print: %s", - heads().length() > 0 ? "" : "NONE"); - for (int m = 0; m < heads().length(); m++) { - tty->print("%6d ", m); heads().at(m)->dump(); - tty->print(" "); tails().at(m)->dump(); - } -} -#endif - // Get all memory nodes of a slice, in reverse order void VLoopMemorySlices::get_slice_in_reverse_order(PhiNode* head, MemNode* tail, GrowableArray &slice) const { + assert(head != nullptr && tail != nullptr, "must be slice with memory state loop"); assert(slice.is_empty(), "start empty"); Node* n = tail; Node* prev = nullptr; @@ -1576,7 +1551,7 @@ void SuperWord::filter_packs_for_alignment() { MemNode const* mem = current->as_constrained()->mem_ref(); Node_List* pack = get_pack(mem); assert(pack != nullptr, "memop of final solution must still be packed"); - _mem_ref_for_main_loop_alignment = mem; + _vpointer_for_main_loop_alignment = &vpointer(mem); _aw_for_main_loop_alignment = pack->size() * mem->memory_size(); } } @@ -1946,7 +1921,9 @@ void PackSet::verify() const { } #endif -bool SuperWord::schedule_and_apply() const { +// Build VTransform from SuperWord Packset, and eventually apply it (create new vectorized C2 loop). +// See description at top of "vtransform.hpp". +bool SuperWord::do_vtransform() const { if (_packset.is_empty()) { return false; } // Make an empty transform. @@ -1959,7 +1936,7 @@ bool SuperWord::schedule_and_apply() const { is_trace_superword_info()); #endif VTransform vtransform(_vloop_analyzer, - _mem_ref_for_main_loop_alignment, + _vpointer_for_main_loop_alignment, _aw_for_main_loop_alignment NOT_PRODUCT(COMMA trace) ); @@ -1988,6 +1965,7 @@ bool SuperWord::schedule_and_apply() const { // Apply the vectorization, i.e. we irreversibly edit the C2 graph. At this point, all // correctness and profitability checks have passed, and the graph was successfully scheduled. +// See description at top of "vtransform.hpp". void VTransform::apply() { #ifndef PRODUCT if (_trace._info || TraceLoopOpts) { @@ -2002,9 +1980,6 @@ void VTransform::apply() { Compile* C = phase()->C; C->print_method(PHASE_AUTO_VECTORIZATION1_BEFORE_APPLY, 4, cl()); - _graph.apply_memops_reordering_with_schedule(); - C->print_method(PHASE_AUTO_VECTORIZATION2_AFTER_REORDER, 4, cl()); - adjust_pre_loop_limit_to_align_main_loop_vectors(); C->print_method(PHASE_AUTO_VECTORIZATION3_AFTER_ADJUST_LIMIT, 4, cl()); @@ -2016,102 +1991,11 @@ void VTransform::apply() { C->print_method(PHASE_AUTO_VECTORIZATION5_AFTER_APPLY, 4, cl()); } -// We prepare the memory graph for the replacement of scalar memops with vector memops. -// We reorder all slices in parallel, ensuring that the memops inside each slice are -// ordered according to the _schedule. This means that all packed memops are consecutive -// in the memory graph after the reordering. -void VTransformGraph::apply_memops_reordering_with_schedule() const { -#ifndef PRODUCT - assert(is_scheduled(), "must be already scheduled"); - if (_trace._info) { - print_memops_schedule(); - } -#endif - - ResourceMark rm; - int max_slices = phase()->C->num_alias_types(); - // When iterating over the schedule, we keep track of the current memory state, - // which is the Phi or a store in the loop. - GrowableArray current_state_in_slice(max_slices, max_slices, nullptr); - // The memory state after the loop is the last store inside the loop. If we reorder the - // loop we may have a different last store, and we need to adjust the uses accordingly. - GrowableArray old_last_store_in_slice(max_slices, max_slices, nullptr); - - const GrowableArray& mem_slice_head = _vloop_analyzer.memory_slices().heads(); - - // (1) Set up the initial memory state from Phi. And find the old last store. - for (int i = 0; i < mem_slice_head.length(); i++) { - Node* phi = mem_slice_head.at(i); - assert(phi->is_Phi(), "must be phi"); - int alias_idx = phase()->C->get_alias_index(phi->adr_type()); - current_state_in_slice.at_put(alias_idx, phi); - - // If we have a memory phi, we have a last store in the loop, find it over backedge. - StoreNode* last_store = phi->in(2)->as_Store(); - old_last_store_in_slice.at_put(alias_idx, last_store); - } - - // (2) Walk over schedule, append memops to the current state - // of that slice. If it is a Store, we take it as the new state. - for_each_memop_in_schedule([&] (MemNode* n) { - assert(n->is_Load() || n->is_Store(), "only loads or stores"); - int alias_idx = phase()->C->get_alias_index(n->adr_type()); - Node* current_state = current_state_in_slice.at(alias_idx); - if (current_state == nullptr) { - // If there are only loads in a slice, we never update the memory - // state in the loop, hence there is no phi for the memory state. - // We just keep the old memory state that was outside the loop. - assert(n->is_Load() && !in_bb(n->in(MemNode::Memory)), - "only loads can have memory state from outside loop"); - } else { - igvn().replace_input_of(n, MemNode::Memory, current_state); - if (n->is_Store()) { - current_state_in_slice.at_put(alias_idx, n); - } - } - }); - - // (3) For each slice, we add the current state to the backedge - // in the Phi. Further, we replace uses of the old last store - // with uses of the new last store (current_state). - GrowableArray uses_after_loop; - for (int i = 0; i < mem_slice_head.length(); i++) { - Node* phi = mem_slice_head.at(i); - int alias_idx = phase()->C->get_alias_index(phi->adr_type()); - Node* current_state = current_state_in_slice.at(alias_idx); - assert(current_state != nullptr, "slice is mapped"); - assert(current_state != phi, "did some work in between"); - assert(current_state->is_Store(), "sanity"); - igvn().replace_input_of(phi, 2, current_state); - - // Replace uses of old last store with current_state (new last store) - // Do it in two loops: first find all the uses, and change the graph - // in as second loop so that we do not break the iterator. - Node* last_store = old_last_store_in_slice.at(alias_idx); - assert(last_store != nullptr, "we have a old last store"); - uses_after_loop.clear(); - for (DUIterator_Fast kmax, k = last_store->fast_outs(kmax); k < kmax; k++) { - Node* use = last_store->fast_out(k); - if (!in_bb(use)) { - uses_after_loop.push(use); - } - } - for (int k = 0; k < uses_after_loop.length(); k++) { - Node* use = uses_after_loop.at(k); - for (uint j = 0; j < use->req(); j++) { - Node* def = use->in(j); - if (def == last_store) { - igvn().replace_input_of(use, j, current_state); - } - } - } - } -} - void VTransformGraph::apply_vectorization_for_each_vtnode(uint& max_vector_length, uint& max_vector_width) const { ResourceMark rm; VTransformApplyState apply_state(_vloop_analyzer, _vtnodes.length()); + // Apply: transform the node and connect with inputs (no backedges). for (int i = 0; i < _schedule.length(); i++) { VTransformNode* vtn = _schedule.at(i); VTransformApplyResult result = vtn->apply(apply_state); @@ -2121,6 +2005,16 @@ void VTransformGraph::apply_vectorization_for_each_vtnode(uint& max_vector_lengt max_vector_length = MAX2(max_vector_length, result.vector_length()); max_vector_width = MAX2(max_vector_width, result.vector_width()); } + + // Cleanup: connect backedges + for (int i = 0; i < _schedule.length(); i++) { + VTransformNode* vtn = _schedule.at(i); + vtn->apply_backedge(apply_state); + } + + // Memory uses after the loop: used to connect to old last store, + // now need to connect to new last store. + apply_state.fix_memory_state_uses_after_loop(); } // We call "apply" on every VTransformNode, which replaces the packed scalar nodes with vector nodes. @@ -2774,10 +2668,10 @@ bool VLoopMemorySlices::same_memory_slice(MemNode* m1, MemNode* m2) const { _vloop.phase()->C->get_alias_index(m2->adr_type()); } -LoadNode::ControlDependency VTransformLoadVectorNode::control_dependency() const { +LoadNode::ControlDependency SuperWordVTransformBuilder::load_control_dependency(const Node_List* pack) const { LoadNode::ControlDependency dep = LoadNode::DependsOnlyOnTest; - for (int i = 0; i < nodes().length(); i++) { - Node* n = nodes().at(i); + for (uint i = 0; i < pack->size(); i++) { + Node* n = pack->at(i); assert(n->is_Load(), "only meaningful for loads"); if (!n->depends_only_on_test()) { if (n->as_Load()->has_unknown_control_dependency() && @@ -2795,22 +2689,24 @@ LoadNode::ControlDependency VTransformLoadVectorNode::control_dependency() const // Find the memop pack with the maximum vector width, unless they were already // determined (e.g. by SuperWord::filter_packs_for_alignment()). -void VTransform::determine_mem_ref_and_aw_for_main_loop_alignment() { - if (_mem_ref_for_main_loop_alignment != nullptr) { - assert(VLoop::vectors_should_be_aligned(), "mem_ref only set if filtered for alignment"); +void VTransform::determine_vpointer_and_aw_for_main_loop_alignment() { + if (_vpointer_for_main_loop_alignment != nullptr) { + assert(VLoop::vectors_should_be_aligned(), "vpointer_for_main_loop_alignment only set if filtered for alignment"); return; } - MemNode const* mem_ref = nullptr; + VPointer const* vpointer = nullptr; int max_aw = 0; + bool vpointer_is_load = false; const GrowableArray& vtnodes = _graph.vtnodes(); for (int i = 0; i < vtnodes.length(); i++) { VTransformMemVectorNode* vtn = vtnodes.at(i)->isa_MemVector(); if (vtn == nullptr) { continue; } - MemNode* p0 = vtn->nodes().at(0)->as_Mem(); - int vw = p0->memory_size() * vtn->nodes().length(); + int vw = vtn->vpointer().size(); + bool vtn_is_load = vtn->is_load_in_loop(); + // Generally, we prefer to align with the largest memory op (load or store). // If there are multiple, then SuperWordAutomaticAlignment determines if we // prefer loads or stores. @@ -2820,15 +2716,16 @@ void VTransform::determine_mem_ref_and_aw_for_main_loop_alignment() { // it is worse if a store is split, and less bad if a load is split. // By default, we have SuperWordAutomaticAlignment=1, i.e. we align with a // store if possible, to avoid splitting that store. - bool prefer_store = mem_ref != nullptr && SuperWordAutomaticAlignment == 1 && mem_ref->is_Load() && p0->is_Store(); - bool prefer_load = mem_ref != nullptr && SuperWordAutomaticAlignment == 2 && mem_ref->is_Store() && p0->is_Load(); + bool prefer_store = SuperWordAutomaticAlignment == 1 && vpointer_is_load && !vtn_is_load; + bool prefer_load = SuperWordAutomaticAlignment == 2 && !vpointer_is_load && vtn_is_load; if (vw > max_aw || (vw == max_aw && (prefer_load || prefer_store))) { + vpointer = &vtn->vpointer(); max_aw = vw; - mem_ref = p0; + vpointer_is_load = vtn_is_load; } } - assert(mem_ref != nullptr && max_aw > 0, "found mem_ref and aw"); - _mem_ref_for_main_loop_alignment = mem_ref; + assert(vpointer != nullptr && max_aw > 0, "found vpointer and aw"); + _vpointer_for_main_loop_alignment = vpointer; _aw_for_main_loop_alignment = max_aw; } @@ -2842,13 +2739,17 @@ void VTransform::determine_mem_ref_and_aw_for_main_loop_alignment() { } \ // Ensure that the main loop vectors are aligned by adjusting the pre loop limit. We memory-align -// the address of "_mem_ref_for_main_loop_alignment" to "_aw_for_main_loop_alignment", which is a +// the address of "_vpointer_for_main_loop_alignment" to "_aw_for_main_loop_alignment", which is a // sufficiently large alignment width. We adjust the pre-loop iteration count by adjusting the // pre-loop limit. void VTransform::adjust_pre_loop_limit_to_align_main_loop_vectors() { - determine_mem_ref_and_aw_for_main_loop_alignment(); - const MemNode* align_to_ref = _mem_ref_for_main_loop_alignment; - const int aw = _aw_for_main_loop_alignment; + determine_vpointer_and_aw_for_main_loop_alignment(); + + assert(cl()->is_main_loop(), "can only do alignment for main loop"); + assert(_vpointer_for_main_loop_alignment != nullptr && + _vpointer_for_main_loop_alignment->is_valid() && + _aw_for_main_loop_alignment > 0, + "must have alignment reference and aw"); if (!VLoop::vectors_should_be_aligned() && SuperWordAutomaticAlignment == 0) { #ifdef ASSERT @@ -2859,8 +2760,8 @@ void VTransform::adjust_pre_loop_limit_to_align_main_loop_vectors() { return; } - assert(align_to_ref != nullptr && aw > 0, "must have alignment reference and aw"); - assert(cl()->is_main_loop(), "can only do alignment for main loop"); + const VPointer& p = *_vpointer_for_main_loop_alignment; + const int aw = _aw_for_main_loop_alignment; // The opaque node for the limit, where we adjust the input Opaque1Node* pre_opaq = _vloop.pre_loop_end()->limit()->as_Opaque1(); @@ -2875,10 +2776,7 @@ void VTransform::adjust_pre_loop_limit_to_align_main_loop_vectors() { Node* orig_limit = pre_opaq->original_loop_limit(); assert(orig_limit != nullptr && igvn().type(orig_limit) != Type::TOP, ""); - const VPointer& p = vpointer(align_to_ref); - assert(p.is_valid(), "sanity"); - - // For the main-loop, we want the address of align_to_ref to be memory aligned + // For the main-loop, we want the address of vpointer p to be memory aligned // with some alignment width (aw, a power of 2). When we enter the main-loop, // we know that iv is equal to the pre-loop limit. If we adjust the pre-loop // limit by executing adjust_pre_iter many extra iterations, we can change the @@ -3013,9 +2911,7 @@ void VTransform::adjust_pre_loop_limit_to_align_main_loop_vectors() { #ifdef ASSERT if (_trace._align_vector) { tty->print_cr("\nVTransform::adjust_pre_loop_limit_to_align_main_loop_vectors:"); - tty->print(" align_to_ref:"); - align_to_ref->dump(); - tty->print(" "); + tty->print(" vpointer_for_main_loop_alignment"); p.print_on(tty); tty->print_cr(" aw: %d", aw); tty->print_cr(" iv_stride: %d", iv_stride); diff --git a/src/hotspot/share/opto/superword.hpp b/src/hotspot/share/opto/superword.hpp index 0940e752f85..118e0aa042c 100644 --- a/src/hotspot/share/opto/superword.hpp +++ b/src/hotspot/share/opto/superword.hpp @@ -410,9 +410,9 @@ class SuperWord : public ResourceObj { PairSet _pairset; PackSet _packset; - // Memory reference, and the alignment width (aw) for which we align the main-loop, + // VPointer, and the alignment width (aw) for which we align the main-loop, // by adjusting the pre-loop limit. - MemNode const* _mem_ref_for_main_loop_alignment; + VPointer const* _vpointer_for_main_loop_alignment; int _aw_for_main_loop_alignment; public: @@ -657,7 +657,7 @@ private: bool is_velt_basic_type_compatible_use_def(Node* use, Node* def) const; - bool schedule_and_apply() const; + bool do_vtransform() const; }; #endif // SHARE_OPTO_SUPERWORD_HPP diff --git a/src/hotspot/share/opto/superwordVTransformBuilder.cpp b/src/hotspot/share/opto/superwordVTransformBuilder.cpp index dbc96c234a9..45c919ccffa 100644 --- a/src/hotspot/share/opto/superwordVTransformBuilder.cpp +++ b/src/hotspot/share/opto/superwordVTransformBuilder.cpp @@ -37,6 +37,10 @@ void SuperWordVTransformBuilder::build() { VectorSet vtn_memory_dependencies; // Shared, but cleared for every vtnode. build_inputs_for_vector_vtnodes(vtn_memory_dependencies); build_inputs_for_scalar_vtnodes(vtn_memory_dependencies); + + // Build vtnodes for all uses of nodes from the loop, and connect them + // as outputs to the nodes in the loop. + build_uses_after_loop(); } void SuperWordVTransformBuilder::build_vector_vtnodes_for_packed_nodes() { @@ -50,8 +54,8 @@ void SuperWordVTransformBuilder::build_vector_vtnodes_for_packed_nodes() { } void SuperWordVTransformBuilder::build_scalar_vtnodes_for_non_packed_nodes() { - for (int i = 0; i < _vloop_analyzer.body().body().length(); i++) { - Node* n = _vloop_analyzer.body().body().at(i); + for (uint i = 0; i < _vloop.lpt()->_body.size(); i++) { + Node* n = _vloop.lpt()->_body.at(i); if (_packset.get_pack(n) != nullptr) { continue; } VTransformNode* vtn = nullptr; @@ -61,6 +65,8 @@ void SuperWordVTransformBuilder::build_scalar_vtnodes_for_non_packed_nodes() { vtn = new (_vtransform.arena()) VTransformMemopScalarNode(_vtransform, mem, mem_p); } else if (n->is_Phi()) { vtn = new (_vtransform.arena()) VTransformLoopPhiNode(_vtransform, n->as_Phi()); + } else if (n->is_CountedLoop()) { + vtn = new (_vtransform.arena()) VTransformCountedLoopNode(_vtransform, n->as_CountedLoop()); } else if (n->is_CFG()) { vtn = new (_vtransform.arena()) VTransformCFGNode(_vtransform, n); } else { @@ -121,8 +127,8 @@ void SuperWordVTransformBuilder::build_inputs_for_vector_vtnodes(VectorSet& vtn_ } void SuperWordVTransformBuilder::build_inputs_for_scalar_vtnodes(VectorSet& vtn_memory_dependencies) { - for (int i = 0; i < _vloop_analyzer.body().body().length(); i++) { - Node* n = _vloop_analyzer.body().body().at(i); + for (uint i = 0; i < _vloop.lpt()->_body.size(); i++) { + Node* n = _vloop.lpt()->_body.at(i); VTransformNode* vtn = get_vtnode(n); if (vtn->isa_Vector() != nullptr) { continue; } vtn_memory_dependencies.clear(); // Add every dependency only once per vtn. @@ -135,18 +141,41 @@ void SuperWordVTransformBuilder::build_inputs_for_scalar_vtnodes(VectorSet& vtn_ init_req_with_scalar(n, vtn, MemNode::ValueIn); add_memory_dependencies_of_node_to_vtnode(n, vtn, vtn_memory_dependencies); } else if (n->is_CountedLoop()) { - continue; // Is "root", has no dependency. - } else if (n->is_Phi()) { - // CountedLoop Phi's: ignore backedge (and entry value). - assert(n->in(0) == _vloop.cl(), "only Phi's from the CountedLoop allowed"); - init_req_with_scalar(n, vtn, 0); - continue; + // Avoid self-loop, it only creates unnecessary issues in scheduling. + init_req_with_scalar(n, vtn, LoopNode::EntryControl); + init_req_with_scalar(n, vtn, LoopNode::LoopBackControl); } else { init_all_req_with_scalars(n, vtn); } } } +// Build vtnodes for all uses of nodes from the loop, and connect them +// as outputs to the nodes in the loop. +void SuperWordVTransformBuilder::build_uses_after_loop() { + for (uint i = 0; i < _vloop.lpt()->_body.size(); i++) { + Node* n = _vloop.lpt()->_body.at(i); + VTransformNode* vtn = get_vtnode(n); + + for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { + Node* use = n->fast_out(i); + + if (!_vloop.in_bb(use)) { + VTransformNode* vtn_use = get_vtnode_or_wrap_as_outer(use); + + // Set all edges + for (uint j = 0; j < use->req(); j++) { + Node* def = use->in(j); + if (n == def && vtn_use->in_req(j) != vtn) { + assert(vtn_use->in_req(j) == nullptr, "should not yet be set"); + vtn_use->init_req(j, vtn); + } + } + } + } + } +} + // Create a vtnode for each pack. No in/out edges set yet. VTransformVectorNode* SuperWordVTransformBuilder::make_vector_vtnode_for_pack(const Node_List* pack) const { Node* p0 = pack->at(0); @@ -159,7 +188,8 @@ VTransformVectorNode* SuperWordVTransformBuilder::make_vector_vtnode_for_pack(co if (p0->is_Load()) { const VPointer& scalar_p = _vloop_analyzer.vpointers().vpointer(p0->as_Load()); const VPointer vector_p(scalar_p.make_with_size(scalar_p.size() * vlen)); - vtn = new (_vtransform.arena()) VTransformLoadVectorNode(_vtransform, properties, vector_p, p0->adr_type()); + const LoadNode::ControlDependency control_dependency = load_control_dependency(pack); + vtn = new (_vtransform.arena()) VTransformLoadVectorNode(_vtransform, properties, vector_p, p0->adr_type(), control_dependency); } else if (p0->is_Store()) { const VPointer& scalar_p = _vloop_analyzer.vpointers().vpointer(p0->as_Store()); const VPointer vector_p(scalar_p.make_with_size(scalar_p.size() * vlen)); @@ -209,7 +239,6 @@ VTransformVectorNode* SuperWordVTransformBuilder::make_vector_vtnode_for_pack(co int vopc = VectorNode::opcode(sopc, bt); vtn = new (_vtransform.arena()) VTransformElementWiseVectorNode(_vtransform, p0->req(), properties, vopc); } - vtn->set_nodes(pack); return vtn; } @@ -276,15 +305,15 @@ VTransformNode* SuperWordVTransformBuilder::get_or_make_vtnode_vector_input_at_i // case of a ConvL2I, it can be int or some narrower type such // as short etc. But given we replicate the input of the Convert // node, we have to use the input type instead. - BasicType element_type = p0->is_Convert() ? p0->in(1)->bottom_type()->basic_type() : _vloop_analyzer.types().velt_basic_type(p0); - if (index == 2 && VectorNode::is_scalar_rotate(p0) && element_type == T_LONG) { + BasicType element_bt = p0->is_Convert() ? p0->in(1)->bottom_type()->basic_type() : _vloop_analyzer.types().velt_basic_type(p0); + if (index == 2 && VectorNode::is_scalar_rotate(p0) && element_bt == T_LONG) { // Scalar rotate has int rotation value, but the scalar rotate expects longs. assert(same_input->bottom_type()->isa_int(), "scalar rotate expects int rotation"); VTransformNode* conv = new (_vtransform.arena()) VTransformConvI2LNode(_vtransform); conv->init_req(1, same_input_vtn); same_input_vtn = conv; } - VTransformNode* replicate = new (_vtransform.arena()) VTransformReplicateNode(_vtransform, pack->size(), element_type); + VTransformNode* replicate = new (_vtransform.arena()) VTransformReplicateNode(_vtransform, pack->size(), element_bt); replicate->init_req(1, same_input_vtn); return replicate; } @@ -307,6 +336,7 @@ VTransformNode* SuperWordVTransformBuilder::get_vtnode_or_wrap_as_outer(Node* n) assert(!_vloop.in_bb(n), "only nodes outside the loop can be input nodes to the loop"); vtn = new (_vtransform.arena()) VTransformOuterNode(_vtransform, n); map_node_to_vtnode(n, vtn); + assert(vtn == get_vtnode_or_null(n), "consistency"); return vtn; } diff --git a/src/hotspot/share/opto/superwordVTransformBuilder.hpp b/src/hotspot/share/opto/superwordVTransformBuilder.hpp index 6ed8480209a..cc9dd225f01 100644 --- a/src/hotspot/share/opto/superwordVTransformBuilder.hpp +++ b/src/hotspot/share/opto/superwordVTransformBuilder.hpp @@ -56,6 +56,7 @@ private: void build_scalar_vtnodes_for_non_packed_nodes(); void build_inputs_for_vector_vtnodes(VectorSet& vtn_memory_dependencies); void build_inputs_for_scalar_vtnodes(VectorSet& vtn_memory_dependencies); + void build_uses_after_loop(); // Helper methods for building VTransform. VTransformNode* get_vtnode_or_null(Node* n) const { @@ -82,6 +83,7 @@ private: void init_all_req_with_scalars(Node* n, VTransformNode* vtn); void init_all_req_with_vectors(const Node_List* pack, VTransformNode* vtn); void add_memory_dependencies_of_node_to_vtnode(Node* n, VTransformNode* vtn, VectorSet& vtn_memory_dependencies); + LoadNode::ControlDependency load_control_dependency(const Node_List* pack) const; }; #endif // SHARE_OPTO_SUPERWORD_VTRANSFORM_BUILDER_HPP diff --git a/src/hotspot/share/opto/vectorization.cpp b/src/hotspot/share/opto/vectorization.cpp index 8e0f0980ff7..5c4e15fdbb9 100644 --- a/src/hotspot/share/opto/vectorization.cpp +++ b/src/hotspot/share/opto/vectorization.cpp @@ -182,6 +182,11 @@ VStatus VLoopAnalyzer::setup_submodules_helper() { _reductions.mark_reductions(); } + VStatus body_status = _body.construct(); + if (!body_status.is_success()) { + return body_status; + } + _memory_slices.find_memory_slices(); // If there is no memory slice detected, it means there is no store. @@ -192,11 +197,6 @@ VStatus VLoopAnalyzer::setup_submodules_helper() { return VStatus::make_failure(VLoopAnalyzer::FAILURE_NO_REDUCTION_OR_STORE); } - VStatus body_status = _body.construct(); - if (!body_status.is_success()) { - return body_status; - } - _types.compute_vector_element_type(); _vpointers.compute_vpointers(); @@ -206,6 +206,64 @@ VStatus VLoopAnalyzer::setup_submodules_helper() { return VStatus::make_success(); } +// There are 2 kinds of slices: +// - No memory phi: only loads. All have the same input memory state from before the loop. +// - With memory phi. Chain of memory operations inside the loop. +void VLoopMemorySlices::find_memory_slices() { + Compile* C = _vloop.phase()->C; + // We iterate over the body, which is topologically sorted. Hence, if there is a phi + // in a slice, we will find it first, and the loads and stores afterwards. + for (int i = 0; i < _body.body().length(); i++) { + Node* n = _body.body().at(i); + if (n->is_memory_phi()) { + // Memory slice with stores (and maybe loads) + PhiNode* phi = n->as_Phi(); + int alias_idx = C->get_alias_index(phi->adr_type()); + assert(_inputs.at(alias_idx) == nullptr, "did not yet touch this slice"); + _inputs.at_put(alias_idx, phi->in(1)); + _heads.at_put(alias_idx, phi); + } else if (n->is_Load()) { + LoadNode* load = n->as_Load(); + int alias_idx = C->get_alias_index(load->adr_type()); + PhiNode* head = _heads.at(alias_idx); + if (head == nullptr) { + // We did not find a phi on this slice yet -> must be a slice with only loads. + assert(_inputs.at(alias_idx) == nullptr || _inputs.at(alias_idx) == load->in(1), + "not yet touched or the same input"); + _inputs.at_put(alias_idx, load->in(1)); + } // else: the load belongs to a slice with a phi that already set heads and inputs. +#ifdef ASSERT + } else if (n->is_Store()) { + // Found a store. Make sure it is in a slice with a Phi. + StoreNode* store = n->as_Store(); + int alias_idx = C->get_alias_index(store->adr_type()); + PhiNode* head = _heads.at(alias_idx); + assert(head != nullptr, "should have found a mem phi for this slice"); +#endif + } + } + NOT_PRODUCT( if (_vloop.is_trace_memory_slices()) { print(); } ) +} + +#ifndef PRODUCT +void VLoopMemorySlices::print() const { + tty->print_cr("\nVLoopMemorySlices::print: %s", + heads().length() > 0 ? "" : "NONE"); + for (int i = 0; i < _inputs.length(); i++) { + Node* input = _inputs.at(i); + PhiNode* head = _heads.at(i); + if (input != nullptr) { + tty->print("%3d input", i); input->dump(); + if (head == nullptr) { + tty->print_cr(" load only"); + } else { + tty->print(" head "); head->dump(); + } + } + } +} +#endif + void VLoopVPointers::compute_vpointers() { count_vpointers(); allocate_vpointers_array(); @@ -267,7 +325,6 @@ void VLoopVPointers::print() const { // the edge, i.e. spaw the order. void VLoopDependencyGraph::construct() { const GrowableArray& mem_slice_heads = _memory_slices.heads(); - const GrowableArray& mem_slice_tails = _memory_slices.tails(); ResourceMark rm; GrowableArray slice_nodes; @@ -277,7 +334,10 @@ void VLoopDependencyGraph::construct() { // For each memory slice, create the memory subgraph for (int i = 0; i < mem_slice_heads.length(); i++) { PhiNode* head = mem_slice_heads.at(i); - MemNode* tail = mem_slice_tails.at(i); + // If there is no head (memory-phi) for this slice, then we have either no memops + // in the loop, or only loads. We do not need to add any memory edges in that case. + if (head == nullptr) { continue; } + MemNode* tail = head->in(2)->as_Mem(); _memory_slices.get_slice_in_reverse_order(head, tail, slice_nodes); diff --git a/src/hotspot/share/opto/vectorization.hpp b/src/hotspot/share/opto/vectorization.hpp index b39e46cbf35..e006589cce9 100644 --- a/src/hotspot/share/opto/vectorization.hpp +++ b/src/hotspot/share/opto/vectorization.hpp @@ -379,37 +379,6 @@ private: static Node* original_input(const Node* n, uint i); }; -// Submodule of VLoopAnalyzer. -// Find the memory slices in the loop. -class VLoopMemorySlices : public StackObj { -private: - const VLoop& _vloop; - - GrowableArray _heads; - GrowableArray _tails; - -public: - VLoopMemorySlices(Arena* arena, const VLoop& vloop) : - _vloop(vloop), - _heads(arena, 8, 0, nullptr), - _tails(arena, 8, 0, nullptr) {}; - NONCOPYABLE(VLoopMemorySlices); - - void find_memory_slices(); - - const GrowableArray& heads() const { return _heads; } - const GrowableArray& tails() const { return _tails; } - - // Get all memory nodes of a slice, in reverse order - void get_slice_in_reverse_order(PhiNode* head, MemNode* tail, GrowableArray& slice) const; - - bool same_memory_slice(MemNode* m1, MemNode* m2) const; - -#ifndef PRODUCT - void print() const; -#endif -}; - // Submodule of VLoopAnalyzer. // Finds all nodes in the body, and creates a mapping node->_idx to a body_idx. // This mapping is used so that subsequent datastructures sizes only grow with @@ -461,6 +430,73 @@ private: } }; +// Submodule of VLoopAnalyzer. +// Find the memory slices in the loop. There are 3 kinds of slices: +// 1. no use in loop: inputs(i) = nullptr, heads(i) = nullptr +// 2. stores in loop: inputs(i) = entry_mem, heads(i) = phi_mem +// +// = entry_mem +// | +// CountedLoop | +-----------------------+ +// | v v | +// phi_mem | +// | | +// | +// | | +// +---------------------------+ +// | +// +// +// Note: the mem uses after the loop are dependent on the last store in the loop. +// Once we vectorize, we may reorder the loads and stores, and replace +// scalar mem ops with vector mem ops. We will have to make sure that all +// uses after the loop use the new last store. +// See: VTransformApplyState::fix_memory_state_uses_after_loop +// +// 3. only loads but no stores in loop: inputs(i) = entry_mem, heads(i) = nullptr +// +// = entry_mem +// | | +// | CountedLoop | +// | | | +// | +// | +// +// +// Note: the mem uses after the loop are NOT dependent any mem ops in the loop, +// since there are no stores. +// +class VLoopMemorySlices : public StackObj { +private: + const VLoop& _vloop; + const VLoopBody& _body; + + GrowableArray _inputs; + GrowableArray _heads; + +public: + VLoopMemorySlices(Arena* arena, const VLoop& vloop, const VLoopBody& body) : + _vloop(vloop), + _body(body), + _inputs(arena, num_slices(), num_slices(), nullptr), + _heads(arena, num_slices(), num_slices(), nullptr) {}; + NONCOPYABLE(VLoopMemorySlices); + + const GrowableArray& inputs() const { return _inputs; } + const GrowableArray& heads() const { return _heads; } + + void find_memory_slices(); + void get_slice_in_reverse_order(PhiNode* head, MemNode* tail, GrowableArray& slice) const; + bool same_memory_slice(MemNode* m1, MemNode* m2) const; + +private: +#ifndef PRODUCT + void print() const; +#endif + + int num_slices() const { return _vloop.phase()->C->num_alias_types(); } +}; + // Submodule of VLoopAnalyzer. // Compute the vector element type for every node in the loop body. // We need to do this to be able to vectorize the narrower integer @@ -737,8 +773,8 @@ private: // Submodules VLoopReductions _reductions; - VLoopMemorySlices _memory_slices; VLoopBody _body; + VLoopMemorySlices _memory_slices; VLoopTypes _types; VLoopVPointers _vpointers; VLoopDependencyGraph _dependency_graph; @@ -749,8 +785,8 @@ public: _arena(mtCompiler, Arena::Tag::tag_superword), _success(false), _reductions (&_arena, vloop), - _memory_slices (&_arena, vloop), _body (&_arena, vloop, vshared), + _memory_slices (&_arena, vloop, _body), _types (&_arena, vloop, _body), _vpointers (&_arena, vloop, _body), _dependency_graph(&_arena, vloop, _body, _memory_slices, _vpointers) diff --git a/src/hotspot/share/opto/vtransform.cpp b/src/hotspot/share/opto/vtransform.cpp index 8c1210a5a09..27c541c2732 100644 --- a/src/hotspot/share/opto/vtransform.cpp +++ b/src/hotspot/share/opto/vtransform.cpp @@ -78,6 +78,10 @@ bool VTransformGraph::schedule() { // runtime check, see VTransform::apply_speculative_aliasing_runtime_checks. for (uint i = 0; i < vtn->out_strong_edges(); i++) { VTransformNode* use = vtn->out_strong_edge(i); + + // Skip LoopPhi backedge. + if ((use->isa_LoopPhi() != nullptr || use->isa_CountedLoop() != nullptr) && use->in_req(2) == vtn) { continue; } + if (post_visited.test(use->_idx)) { continue; } if (pre_visited.test(use->_idx)) { // Cycle detected! @@ -120,6 +124,11 @@ void VTransformGraph::collect_nodes_without_strong_in_edges(GrowableArrayhas_strong_in_edge()) { stack.push(vtn); } + // If an Outer node has both inputs and outputs, we will most likely have cycles in the final graph. + // This is not a correctness problem, but it just will prevent vectorization. If this ever happens + // try to find a way to avoid the cycle somehow. + assert(vtn->isa_Outer() == nullptr || (vtn->has_strong_in_edge() != (vtn->out_strong_edges() > 0)), + "Outer nodes should either be inputs or outputs, but not both, otherwise we may get cycles"); } } @@ -717,28 +726,111 @@ Node* VTransformApplyState::transformed_node(const VTransformNode* vtn) const { return n; } +void VTransformApplyState::init_memory_states_and_uses_after_loop() { + const GrowableArray& inputs = _vloop_analyzer.memory_slices().inputs(); + const GrowableArray& heads = _vloop_analyzer.memory_slices().heads(); + for (int i = 0; i < inputs.length(); i++) { + PhiNode* head = heads.at(i); + if (head != nullptr) { + // Slice with Phi (i.e. with stores) -> start with the phi (phi_mem) + _memory_states.at_put(i, head); + + // Remember uses outside the loop of the last memory state (store). + StoreNode* last_store = head->in(2)->as_Store(); + assert(vloop().in_bb(last_store), "backedge store should be in the loop"); + for (DUIterator_Fast jmax, j = last_store->fast_outs(jmax); j < jmax; j++) { + Node* use = last_store->fast_out(j); + if (!vloop().in_bb(use)) { + for (uint k = 0; k < use->req(); k++) { + if (use->in(k) == last_store) { + _memory_state_uses_after_loop.push(MemoryStateUseAfterLoop(use, k, i)); + } + } + } + } + } else { + // Slice without Phi (i.e. only loads) -> use the input state (entry_mem) + _memory_states.at_put(i, inputs.at(i)); + } + } +} + +// We may have reordered the scalar stores, or replaced them with vectors. Now +// the last memory state in the loop may have changed. Thus, we need to change +// the uses of the old last memory state the new last memory state. +void VTransformApplyState::fix_memory_state_uses_after_loop() { + for (int i = 0; i < _memory_state_uses_after_loop.length(); i++) { + MemoryStateUseAfterLoop& use = _memory_state_uses_after_loop.at(i); + Node* last_state = memory_state(use._alias_idx); + phase()->igvn().replace_input_of(use._use, use._in_idx, last_state); + } +} + +void VTransformNode::apply_vtn_inputs_to_node(Node* n, VTransformApplyState& apply_state) const { + PhaseIdealLoop* phase = apply_state.phase(); + for (uint i = 0; i < req(); i++) { + VTransformNode* vtn_def = in_req(i); + if (vtn_def != nullptr) { + Node* def = apply_state.transformed_node(vtn_def); + phase->igvn().replace_input_of(n, i, def); + } + } +} + VTransformApplyResult VTransformMemopScalarNode::apply(VTransformApplyState& apply_state) const { - // This was just wrapped. Now we simply unwrap without touching the inputs. + apply_vtn_inputs_to_node(_node, apply_state); + // The memory state has to be applied separately: the vtn does not hold it. This allows reordering. + Node* mem = apply_state.memory_state(_node->adr_type()); + apply_state.phase()->igvn().replace_input_of(_node, 1, mem); + if (_node->is_Store()) { + apply_state.set_memory_state(_node->adr_type(), _node); + } + return VTransformApplyResult::make_scalar(_node); } VTransformApplyResult VTransformDataScalarNode::apply(VTransformApplyState& apply_state) const { - // This was just wrapped. Now we simply unwrap without touching the inputs. + apply_vtn_inputs_to_node(_node, apply_state); return VTransformApplyResult::make_scalar(_node); } VTransformApplyResult VTransformLoopPhiNode::apply(VTransformApplyState& apply_state) const { - // This was just wrapped. Now we simply unwrap without touching the inputs. + PhaseIdealLoop* phase = apply_state.phase(); + Node* in0 = apply_state.transformed_node(in_req(0)); + Node* in1 = apply_state.transformed_node(in_req(1)); + phase->igvn().replace_input_of(_node, 0, in0); + phase->igvn().replace_input_of(_node, 1, in1); + // Note: the backedge is hooked up later. return VTransformApplyResult::make_scalar(_node); } +// Cleanup backedges. In the schedule, the backedges come after their phis. Hence, +// we only have the transformed backedges after the phis are already transformed. +// We hook the backedges into the phis now, during cleanup. +void VTransformLoopPhiNode::apply_backedge(VTransformApplyState& apply_state) const { + PhaseIdealLoop* phase = apply_state.phase(); + if (_node->is_memory_phi()) { + // Memory phi/backedge + // The last memory state of that slice is the backedge. + Node* last_state = apply_state.memory_state(_node->adr_type()); + phase->igvn().replace_input_of(_node, 2, last_state); + } else { + // Data phi/backedge + Node* in2 = apply_state.transformed_node(in_req(2)); + phase->igvn().replace_input_of(_node, 2, in2); + } +} + VTransformApplyResult VTransformCFGNode::apply(VTransformApplyState& apply_state) const { - // This was just wrapped. Now we simply unwrap without touching the inputs. + // We do not modify the inputs of the CountedLoop (and certainly not its backedge) + if (!_node->is_CountedLoop()) { + apply_vtn_inputs_to_node(_node, apply_state); + } return VTransformApplyResult::make_scalar(_node); } VTransformApplyResult VTransformOuterNode::apply(VTransformApplyState& apply_state) const { - // This was just wrapped. Now we simply unwrap without touching the inputs. + apply_vtn_inputs_to_node(_node, apply_state); return VTransformApplyResult::make_scalar(_node); } @@ -797,7 +889,7 @@ VTransformApplyResult VTransformElementWiseVectorNode::apply(VTransformApplyStat vn = VectorNode::make(_vector_opcode, in1, in2, in3, vt); // ternary } - register_new_node_from_vectorization_and_replace_scalar_nodes(apply_state, vn); + register_new_node_from_vectorization(apply_state, vn); return VTransformApplyResult::make_vector(vn); } @@ -812,7 +904,7 @@ VTransformApplyResult VTransformElementWiseLongOpWithCastToIntVectorNode::apply( register_new_node_from_vectorization(apply_state, long_vn); // Cast long -> int, to mimic the scalar long -> int operation. VectorNode* vn = VectorCastNode::make(Op_VectorCastL2X, long_vn, T_INT, vlen); - register_new_node_from_vectorization_and_replace_scalar_nodes(apply_state, vn); + register_new_node_from_vectorization(apply_state, vn); return VTransformApplyResult::make_vector(vn); } @@ -824,7 +916,7 @@ VTransformApplyResult VTransformReinterpretVectorNode::apply(VTransformApplyStat Node* in1 = apply_state.transformed_node(in_req(1)); VectorNode* vn = new VectorReinterpretNode(in1, src_vt, dst_vt); - register_new_node_from_vectorization_and_replace_scalar_nodes(apply_state, vn); + register_new_node_from_vectorization(apply_state, vn); return VTransformApplyResult::make_vector(vn); } @@ -843,7 +935,7 @@ VTransformApplyResult VTransformBoolVectorNode::apply(VTransformApplyState& appl PhaseIdealLoop* phase = apply_state.phase(); ConINode* mask_node = phase->intcon((int)mask); VectorNode* vn = new VectorMaskCmpNode(mask, cmp_in1, cmp_in2, mask_node, vt); - register_new_node_from_vectorization_and_replace_scalar_nodes(apply_state, vn); + register_new_node_from_vectorization(apply_state, vn); return VTransformApplyResult::make_vector(vn); } @@ -852,7 +944,7 @@ VTransformApplyResult VTransformReductionVectorNode::apply(VTransformApplyState& Node* vec = apply_state.transformed_node(in_req(2)); ReductionNode* vn = ReductionNode::make(scalar_opcode(), nullptr, init, vec, element_basic_type()); - register_new_node_from_vectorization_and_replace_scalar_nodes(apply_state, vn); + register_new_node_from_vectorization(apply_state, vn); return VTransformApplyResult::make_vector(vn, vn->vect_type()); } @@ -861,10 +953,9 @@ VTransformApplyResult VTransformLoadVectorNode::apply(VTransformApplyState& appl uint vlen = vector_length(); BasicType bt = element_basic_type(); - LoadNode* first = nodes().at(0)->as_Load(); + // The memory state has to be applied separately: the vtn does not hold it. This allows reordering. Node* ctrl = apply_state.transformed_node(in_req(MemNode::Control)); - // first has the correct memory state, determined by VTransformGraph::apply_memops_reordering_with_schedule - Node* mem = first->in(MemNode::Memory); + Node* mem = apply_state.memory_state(_adr_type); Node* adr = apply_state.transformed_node(in_req(MemNode::Address)); // Set the memory dependency of the LoadVector as early as possible. @@ -880,10 +971,9 @@ VTransformApplyResult VTransformLoadVectorNode::apply(VTransformApplyState& appl } } - LoadVectorNode* vn = LoadVectorNode::make(sopc, ctrl, mem, adr, _adr_type, vlen, bt, - control_dependency()); + LoadVectorNode* vn = LoadVectorNode::make(sopc, ctrl, mem, adr, _adr_type, vlen, bt, _control_dependency); DEBUG_ONLY( if (VerifyAlignVector) { vn->set_must_verify_alignment(); } ) - register_new_node_from_vectorization_and_replace_scalar_nodes(apply_state, vn); + register_new_node_from_vectorization(apply_state, vn); return VTransformApplyResult::make_vector(vn, vn->vect_type()); } @@ -891,27 +981,17 @@ VTransformApplyResult VTransformStoreVectorNode::apply(VTransformApplyState& app int sopc = scalar_opcode(); uint vlen = vector_length(); - StoreNode* first = nodes().at(0)->as_Store(); + // The memory state has to be applied separately: the vtn does not hold it. This allows reordering. Node* ctrl = apply_state.transformed_node(in_req(MemNode::Control)); - // first has the correct memory state, determined by VTransformGraph::apply_memops_reordering_with_schedule - Node* mem = first->in(MemNode::Memory); + Node* mem = apply_state.memory_state(_adr_type); Node* adr = apply_state.transformed_node(in_req(MemNode::Address)); Node* value = apply_state.transformed_node(in_req(MemNode::ValueIn)); StoreVectorNode* vn = StoreVectorNode::make(sopc, ctrl, mem, adr, _adr_type, value, vlen); DEBUG_ONLY( if (VerifyAlignVector) { vn->set_must_verify_alignment(); } ) - register_new_node_from_vectorization_and_replace_scalar_nodes(apply_state, vn); - return VTransformApplyResult::make_vector(vn, vn->vect_type()); -} - -void VTransformVectorNode::register_new_node_from_vectorization_and_replace_scalar_nodes(VTransformApplyState& apply_state, Node* vn) const { - PhaseIdealLoop* phase = apply_state.phase(); register_new_node_from_vectorization(apply_state, vn); - - for (int i = 0; i < _nodes.length(); i++) { - Node* n = _nodes.at(i); - phase->igvn().replace_node(n, vn); - } + apply_state.set_memory_state(_adr_type, vn); + return VTransformApplyResult::make_vector(vn, vn->vect_type()); } void VTransformNode::register_new_node_from_vectorization(VTransformApplyState& apply_state, Node* vn) const { @@ -944,15 +1024,6 @@ void VTransformGraph::print_schedule() const { } } -void VTransformGraph::print_memops_schedule() const { - tty->print_cr("\nVTransformGraph::print_memops_schedule:"); - int i = 0; - for_each_memop_in_schedule([&] (MemNode* mem) { - tty->print(" %3d: ", i++); - mem->dump(); - }); -} - void VTransformNode::print() const { tty->print("%3d %s (", _idx, name()); for (uint i = 0; i < _req; i++) { diff --git a/src/hotspot/share/opto/vtransform.hpp b/src/hotspot/share/opto/vtransform.hpp index 9a4e4de01a2..a004962eea7 100644 --- a/src/hotspot/share/opto/vtransform.hpp +++ b/src/hotspot/share/opto/vtransform.hpp @@ -39,7 +39,7 @@ // // This is the life-cycle of a VTransform: // - Construction: -// - From SuperWord, with the SuperWordVTransformBuilder. +// - From SuperWord PackSet, with the SuperWordVTransformBuilder. // // - Future Plans: optimize, if-conversion, etc. // @@ -49,8 +49,16 @@ // // - Apply: // - Changes to the C2 IR are only made once the "apply" method is called. +// - Align the main loop, by adjusting pre loop limit. +// - Add speculative runtime checks (alignment and aliasing). // - Each vtnode generates its corresponding scalar and vector C2 nodes, -// possibly replacing old scalar C2 nodes. +// possibly replacing old scalar C2 nodes. We apply each vtnode in order +// of the schedule, so that all input vtnodes are already applied, i.e. +// all input vtnodes have already generated the transformed C2 nodes. +// - We also build the new memory graph on the fly. The schedule may have +// reordered the memory operations, and so we cannot use the old memory +// graph, but must build it from the scheduled order. We keep track of +// the current memory state in VTransformApplyState. // // Future Plans with VTransform: // - Cost model: estimate if vectorization is profitable. @@ -65,6 +73,7 @@ class VTransformMemopScalarNode; class VTransformDataScalarNode; class VTransformLoopPhiNode; class VTransformCFGNode; +class VTransformCountedLoopNode; class VTransformOuterNode; class VTransformVectorNode; class VTransformElementWiseVectorNode; @@ -176,7 +185,6 @@ public: bool schedule(); bool has_store_to_load_forwarding_failure(const VLoopAnalyzer& vloop_analyzer) const; - void apply_memops_reordering_with_schedule() const; void apply_vectorization_for_each_vtnode(uint& max_vector_length, uint& max_vector_width) const; private: @@ -187,13 +195,9 @@ private: void collect_nodes_without_strong_in_edges(GrowableArray& stack) const; - template - void for_each_memop_in_schedule(Callback callback) const; - #ifndef PRODUCT void print_vtnodes() const; void print_schedule() const; - void print_memops_schedule() const; void trace_schedule_cycle(const GrowableArray& stack, const VectorSet& pre_visited, const VectorSet& post_visited) const; @@ -215,14 +219,14 @@ private: VTransformGraph _graph; - // Memory reference, and the alignment width (aw) for which we align the main-loop, + // VPointer, and the alignment width (aw) for which we align the main-loop, // by adjusting the pre-loop limit. - MemNode const* _mem_ref_for_main_loop_alignment; + VPointer const* _vpointer_for_main_loop_alignment; int _aw_for_main_loop_alignment; public: VTransform(const VLoopAnalyzer& vloop_analyzer, - MemNode const* mem_ref_for_main_loop_alignment, + VPointer const* vpointer_for_main_loop_alignment, int aw_for_main_loop_alignment NOT_PRODUCT( COMMA const VTransformTrace trace) ) : @@ -231,7 +235,7 @@ public: NOT_PRODUCT(_trace(trace) COMMA) _arena(mtCompiler, Arena::Tag::tag_superword), _graph(_vloop_analyzer, _arena NOT_PRODUCT(COMMA _trace)), - _mem_ref_for_main_loop_alignment(mem_ref_for_main_loop_alignment), + _vpointer_for_main_loop_alignment(vpointer_for_main_loop_alignment), _aw_for_main_loop_alignment(aw_for_main_loop_alignment) {} const VLoopAnalyzer& vloop_analyzer() const { return _vloop_analyzer; } @@ -257,7 +261,7 @@ private: } // Ensure that the main loop vectors are aligned by adjusting the pre loop limit. - void determine_mem_ref_and_aw_for_main_loop_alignment(); + void determine_vpointer_and_aw_for_main_loop_alignment(); void adjust_pre_loop_limit_to_align_main_loop_vectors(); void apply_speculative_alignment_runtime_checks(); @@ -271,7 +275,7 @@ private: }; // Keeps track of the state during "VTransform::apply" -// -> keep track of the already transformed nodes +// -> keep track of the already transformed nodes and the memory state. class VTransformApplyState : public StackObj { private: const VLoopAnalyzer& _vloop_analyzer; @@ -281,11 +285,35 @@ private: // generated def (input) nodes when we are generating the use nodes in "apply". GrowableArray _vtnode_idx_to_transformed_node; + // We keep track of the current memory state in each slice. If the slice has only + // loads (and no phi), then this is always the input memory state from before the + // loop. If there is a memory phi, this is initially the memory phi, and each time + // a store is processed, it is updated to that store. + GrowableArray _memory_states; + + // We need to keep track of the memory uses after the loop, for the slices that + // have a memory phi. + // use->in(in_idx) = + class MemoryStateUseAfterLoop : public StackObj { + public: + Node* _use; + int _in_idx; + int _alias_idx; + + MemoryStateUseAfterLoop(Node* use, int in_idx, int alias_idx) : + _use(use), _in_idx(in_idx), _alias_idx(alias_idx) {} + MemoryStateUseAfterLoop() : MemoryStateUseAfterLoop(nullptr, 0, 0) {} + }; + + GrowableArray _memory_state_uses_after_loop; + public: VTransformApplyState(const VLoopAnalyzer& vloop_analyzer, int num_vtnodes) : _vloop_analyzer(vloop_analyzer), - _vtnode_idx_to_transformed_node(num_vtnodes, num_vtnodes, nullptr) + _vtnode_idx_to_transformed_node(num_vtnodes, num_vtnodes, nullptr), + _memory_states(num_slices(), num_slices(), nullptr) { + init_memory_states_and_uses_after_loop(); } const VLoop& vloop() const { return _vloop_analyzer.vloop(); } @@ -294,6 +322,25 @@ public: void set_transformed_node(VTransformNode* vtn, Node* n); Node* transformed_node(const VTransformNode* vtn) const; + + Node* memory_state(int alias_idx) const { return _memory_states.at(alias_idx); } + void set_memory_state(int alias_idx, Node* n) { _memory_states.at_put(alias_idx, n); } + + Node* memory_state(const TypePtr* adr_type) const { + int alias_idx = phase()->C->get_alias_index(adr_type); + return memory_state(alias_idx); + } + + void set_memory_state(const TypePtr* adr_type, Node* n) { + int alias_idx = phase()->C->get_alias_index(adr_type); + return set_memory_state(alias_idx, n); + } + + void fix_memory_state_uses_after_loop(); + +private: + int num_slices() const { return _vloop_analyzer.memory_slices().heads().length(); } + void init_memory_states_and_uses_after_loop(); }; // The vtnodes (VTransformNode) resemble the C2 IR Nodes, and model a part of the @@ -433,6 +480,8 @@ public: } virtual VTransformMemopScalarNode* isa_MemopScalar() { return nullptr; } + virtual VTransformLoopPhiNode* isa_LoopPhi() { return nullptr; } + virtual VTransformCountedLoopNode* isa_CountedLoop() { return nullptr; } virtual VTransformOuterNode* isa_Outer() { return nullptr; } virtual VTransformVectorNode* isa_Vector() { return nullptr; } virtual VTransformElementWiseVectorNode* isa_ElementWiseVector() { return nullptr; } @@ -448,9 +497,8 @@ public: virtual const VPointer& vpointer() const { ShouldNotReachHere(); } virtual VTransformApplyResult apply(VTransformApplyState& apply_state) const = 0; - - Node* find_transformed_input(int i, const GrowableArray& vnode_idx_to_transformed_node) const; - + virtual void apply_backedge(VTransformApplyState& apply_state) const {}; + void apply_vtn_inputs_to_node(Node* n, VTransformApplyState& apply_state) const; void register_new_node_from_vectorization(VTransformApplyState& apply_state, Node* vn) const; NOT_PRODUCT(virtual const char* name() const = 0;) @@ -510,7 +558,9 @@ public: assert(_node->in(0)->is_Loop(), "phi ctrl must be Loop: %s", _node->in(0)->Name()); } + virtual VTransformLoopPhiNode* isa_LoopPhi() override { return this; } virtual VTransformApplyResult apply(VTransformApplyState& apply_state) const override; + virtual void apply_backedge(VTransformApplyState& apply_state) const override; NOT_PRODUCT(virtual const char* name() const override { return "LoopPhi"; };) NOT_PRODUCT(virtual void print_spec() const override;) }; @@ -531,6 +581,16 @@ public: NOT_PRODUCT(virtual void print_spec() const override;) }; +// Identity transform for CountedLoop, the only CFG node with a backedge. +class VTransformCountedLoopNode : public VTransformCFGNode { +public: + VTransformCountedLoopNode(VTransform& vtransform, CountedLoopNode* n) : + VTransformCFGNode(vtransform, n) {} + + virtual VTransformCountedLoopNode* isa_CountedLoop() override { return this; } + NOT_PRODUCT(virtual const char* name() const override { return "CountedLoop"; };) +}; + // Wrapper node for nodes outside the loop that are inputs to nodes in the loop. // Since we want the loop-internal nodes to be able to reference all inputs as vtnodes, // we must wrap the inputs that are outside the loop into special vtnodes, too. @@ -632,22 +692,9 @@ public: class VTransformVectorNode : public VTransformNode { private: const VTransformVectorNodeProperties _properties; -protected: - GrowableArray _nodes; public: VTransformVectorNode(VTransform& vtransform, const uint req, const VTransformVectorNodeProperties properties) : - VTransformNode(vtransform, req), - _properties(properties), - _nodes(vtransform.arena(), - properties.vector_length(), - properties.vector_length(), - nullptr) {} - - void set_nodes(const Node_List* pack) { - for (uint k = 0; k < pack->size(); k++) { - _nodes.at_put(k, pack->at(k)); - } - } + VTransformNode(vtransform, req), _properties(properties) {} virtual VTransformVectorNode* isa_Vector() override { return this; } void register_new_node_from_vectorization_and_replace_scalar_nodes(VTransformApplyState& apply_state, Node* vn) const; @@ -749,17 +796,23 @@ public: _vpointer(vpointer), _adr_type(adr_type) {} - const GrowableArray& nodes() const { return _nodes; } virtual VTransformMemVectorNode* isa_MemVector() override { return this; } virtual bool is_load_or_store_in_loop() const override { return true; } virtual const VPointer& vpointer() const override { return _vpointer; } }; class VTransformLoadVectorNode : public VTransformMemVectorNode { +private: + const LoadNode::ControlDependency _control_dependency; + public: // req = 3 -> [ctrl, mem, adr] - VTransformLoadVectorNode(VTransform& vtransform, const VTransformVectorNodeProperties properties, const VPointer& vpointer, const TypePtr* adr_type) : - VTransformMemVectorNode(vtransform, 3, properties, vpointer, adr_type) {} + VTransformLoadVectorNode(VTransform& vtransform, + const VTransformVectorNodeProperties properties, + const VPointer& vpointer, + const TypePtr* adr_type, + const LoadNode::ControlDependency control_dependency) : + VTransformMemVectorNode(vtransform, 3, properties, vpointer, adr_type), _control_dependency(control_dependency) {} LoadNode::ControlDependency control_dependency() const; virtual VTransformLoadVectorNode* isa_LoadVector() override { return this; } virtual bool is_load_in_loop() const override { return true; } @@ -777,30 +830,4 @@ public: virtual VTransformApplyResult apply(VTransformApplyState& apply_state) const override; NOT_PRODUCT(virtual const char* name() const override { return "StoreVector"; };) }; - -// Invoke callback on all memops, in the order of the schedule. -template -void VTransformGraph::for_each_memop_in_schedule(Callback callback) const { - assert(_schedule.length() == _vtnodes.length(), "schedule was computed"); - - for (int i = 0; i < _schedule.length(); i++) { - VTransformNode* vtn = _schedule.at(i); - - // We must ignore nodes outside the loop. - if (vtn->isa_Outer() != nullptr) { continue; } - - VTransformMemopScalarNode* scalar = vtn->isa_MemopScalar(); - if (scalar != nullptr) { - callback(scalar->node()); - } - - VTransformMemVectorNode* vector = vtn->isa_MemVector(); - if (vector != nullptr) { - for (int j = 0; j < vector->nodes().length(); j++) { - callback(vector->nodes().at(j)->as_Mem()); - } - } - } -} - #endif // SHARE_OPTO_VTRANSFORM_HPP diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/CompilePhase.java b/test/hotspot/jtreg/compiler/lib/ir_framework/CompilePhase.java index 8b794e13e3f..06b2afa8a67 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/CompilePhase.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/CompilePhase.java @@ -98,9 +98,9 @@ public enum CompilePhase { PHASEIDEALLOOP2( "PhaseIdealLoop 2"), PHASEIDEALLOOP3( "PhaseIdealLoop 3"), AUTO_VECTORIZATION1_BEFORE_APPLY( "AutoVectorization 1, before Apply"), - AUTO_VECTORIZATION2_AFTER_REORDER( "AutoVectorization 2, after Apply Memop Reordering"), - AUTO_VECTORIZATION3_AFTER_ADJUST_LIMIT( "AutoVectorization 3, after Adjusting Pre-loop Limit"), - AUTO_VECTORIZATION4_AFTER_SPECULATIVE_RUNTIME_CHECKS("AutoVectorization 4, after Adding Speculative Runtime Checks"), + AUTO_VECTORIZATION3_AFTER_ADJUST_LIMIT( "AutoVectorization 2, after Adjusting Pre-loop Limit"), + AUTO_VECTORIZATION4_AFTER_SPECULATIVE_RUNTIME_CHECKS("AutoVectorization 3, after Adding Speculative Runtime Checks"), + AUTO_VECTORIZATION5_AFTER_APPLY( "AutoVectorization 4, after Apply"), BEFORE_CCP1( "Before PhaseCCP 1"), CCP1( "PhaseCCP 1"), ITER_GVN2( "Iter GVN 2"), From 862119565db311fe0e02e383fd3493601ed23ea8 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Wed, 8 Oct 2025 05:32:51 +0000 Subject: [PATCH 0101/1639] 8363917: SwitchBootstraps.enumSwitch() args not checked as documented Reviewed-by: liach --- .../java/lang/runtime/SwitchBootstraps.java | 37 ++++++++------ .../lang/runtime/SwitchBootstrapsTest.java | 49 +++++++++++++++++-- 2 files changed, 68 insertions(+), 18 deletions(-) diff --git a/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java b/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java index f4d82595842..99716baf439 100644 --- a/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java +++ b/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java @@ -165,22 +165,22 @@ public final class SwitchBootstraps { * @param lookup Represents a lookup context with the accessibility * privileges of the caller. When used with {@code invokedynamic}, * this is stacked automatically by the VM. - * @param invocationName unused + * @param invocationName unused, {@code null} is permitted * @param invocationType The invocation type of the {@code CallSite} with two parameters, * a reference type, an {@code int}, and {@code int} as a return type. * @param labels case labels - {@code String} and {@code Integer} constants * and {@code Class} and {@code EnumDesc} instances, in any combination * @return a {@code CallSite} returning the first matching element as described above * - * @throws NullPointerException if any argument is {@code null} + * @throws NullPointerException if any argument is {@code null}, unless noted otherwise * @throws IllegalArgumentException if any element in the labels array is null * @throws IllegalArgumentException if the invocation type is not a method type of first parameter of a reference type, - * second parameter of type {@code int} and with {@code int} as its return type, + * second parameter of type {@code int} and with {@code int} as its return type * @throws IllegalArgumentException if {@code labels} contains an element that is not of type {@code String}, * {@code Integer}, {@code Long}, {@code Float}, {@code Double}, {@code Boolean}, - * {@code Class} or {@code EnumDesc}. + * {@code Class} or {@code EnumDesc} * @throws IllegalArgumentException if {@code labels} contains an element that is not of type {@code Boolean} - * when {@code target} is a {@code Boolean.class}. + * when {@code target} is a {@code Boolean.class} * @jvms 4.4.6 The CONSTANT_NameAndType_info Structure * @jvms 4.4.10 The CONSTANT_Dynamic_info and CONSTANT_InvokeDynamic_info Structures */ @@ -255,29 +255,36 @@ public final class SwitchBootstraps { * enum constant's {@link Enum#name()}. * *

    - * If no element in the {@code labels} array matches the target, then - * the method of the call site return the length of the {@code labels} array. + * If for a given {@code target} there is no element in the {@code labels} + * fulfilling one of the above conditions, then the method of the call + * site returns the length of the {@code labels} array. *

    * The value of the {@code restart} index must be between {@code 0} (inclusive) and * the length of the {@code labels} array (inclusive), - * both or an {@link IndexOutOfBoundsException} is thrown. + * or an {@link IndexOutOfBoundsException} is thrown. + * + * @apiNote It is permissible for the {@code labels} array to contain {@code String} + * values that do not represent any enum constants at runtime. * * @param lookup Represents a lookup context with the accessibility * privileges of the caller. When used with {@code invokedynamic}, * this is stacked automatically by the VM. - * @param invocationName unused + * @param invocationName unused, {@code null} is permitted * @param invocationType The invocation type of the {@code CallSite} with two parameters, * an enum type, an {@code int}, and {@code int} as a return type. * @param labels case labels - {@code String} constants and {@code Class} instances, * in any combination * @return a {@code CallSite} returning the first matching element as described above * - * @throws NullPointerException if any argument is {@code null} - * @throws IllegalArgumentException if any element in the labels array is null, if the - * invocation type is not a method type whose first parameter type is an enum type, - * second parameter of type {@code int} and whose return type is {@code int}, - * or if {@code labels} contains an element that is not of type {@code String} or - * {@code Class} of the target enum type. + * @throws NullPointerException if any argument is {@code null}, unless noted otherwise + * @throws IllegalArgumentException if any element in the labels array is null + * @throws IllegalArgumentException if any element in the labels array is an empty {@code String} + * @throws IllegalArgumentException if the invocation type is not a method type + * whose first parameter type is an enum type, + * second parameter of type {@code int} and + * whose return type is {@code int} + * @throws IllegalArgumentException if {@code labels} contains an element that is not of type {@code String} or + * {@code Class} equal to the target enum type * @jvms 4.4.6 The CONSTANT_NameAndType_info Structure * @jvms 4.4.10 The CONSTANT_Dynamic_info and CONSTANT_InvokeDynamic_info Structures */ diff --git a/test/jdk/java/lang/runtime/SwitchBootstrapsTest.java b/test/jdk/java/lang/runtime/SwitchBootstrapsTest.java index a231501894f..8c6132b2815 100644 --- a/test/jdk/java/lang/runtime/SwitchBootstrapsTest.java +++ b/test/jdk/java/lang/runtime/SwitchBootstrapsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -155,23 +155,60 @@ public class SwitchBootstrapsTest { testEnum(E1.B, 0, 0, "B", "C", "A", E1.class); testEnum(E1.B, 1, 3, "B", "C", "A", E1.class); try { - testEnum(E1.B, 1, 3, "B", "C", "A", E2.class); + testEnum(E1.B, 0, -1, E2.class); fail("Didn't get the expected exception."); } catch (IllegalArgumentException ex) { //OK } try { - testEnum(E1.B, 1, 3, "B", "C", "A", String.class); + testEnum(E1.B, 0, -1, String.class); fail("Didn't get the expected exception."); } catch (IllegalArgumentException ex) { //OK } + try { + testEnum(E1.B, 0, -1, 10); + fail("Didn't get the expected exception."); + } catch (IllegalArgumentException ex) { + //OK + } + try { + testEnum(E1.B, 0, -1, new Object()); + fail("Didn't get the expected exception."); + } catch (IllegalArgumentException ex) { + //OK + } + try { + testEnum(E1.B, 0, -1, new Object[] { null }); + fail("Didn't get the expected exception."); + } catch (IllegalArgumentException ex) { + //OK + } + try { + testEnum(E1.B, 0, -1, ""); + fail("Didn't get the expected exception."); + } catch (IllegalArgumentException ex) { + //OK + } + try { + testEnum(E1.B, 0, -1, (Object[]) null); + fail("Didn't get the expected exception."); + } catch (NullPointerException ex) { + //OK + } testEnum(E1.B, 0, 0, "B", "A"); testEnum(E1.A, 0, 1, "B", "A"); testEnum(E1.A, 0, 0, "A", "A", "B"); testEnum(E1.A, 1, 1, "A", "A", "B"); testEnum(E1.A, 2, 3, "A", "A", "B"); testEnum(E1.A, 0, 0); + testEnum(E1.B, 0, 2, "A", "OLD_REMOVED_CONSTANT", "B", E1.class); + testEnum(E1.B, 1, 2, "A", "OLD_REMOVED_CONSTANT", "B", E1.class); + + //null invocation name: + MethodType switchType = MethodType.methodType(int.class, E1.class, int.class); + MethodHandle indy = ((CallSite) BSM_ENUM_SWITCH.invoke(MethodHandles.lookup(), null, switchType)).dynamicInvoker(); + assertEquals((int) indy.invoke(E1.A, 0), 0); } public void testEnumsWithConstants() throws Throwable { @@ -197,6 +234,9 @@ public class SwitchBootstrapsTest { testEnum(E.class, E.A, 0, 0, "A", "B", "C"); testEnum(E.class, E.B, 0, 1, "A", "B", "C"); testEnum(E.class, E.C, 0, 2, "A", "B", "C"); + testEnum(E.class, E.C, 0, 2, "A", "B"); + testEnum(E.class, E.C, 1, 2, "A", "B"); + testEnum(E.class, E.C, 2, 2, "A", "B"); } public void testWrongSwitchTypes() throws Throwable { @@ -279,6 +319,9 @@ public class SwitchBootstrapsTest { } catch (IllegalArgumentException ex) { //OK } + //null invocationName is OK: + BSM_TYPE_SWITCH.invoke(MethodHandles.lookup(), null, switchType, + new Object[] {Object.class}); } private static AtomicBoolean enumInitialized = new AtomicBoolean(); From bd25db1fb8573fc908f7a8a96bca417b1d44689a Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Wed, 8 Oct 2025 07:02:34 +0000 Subject: [PATCH 0102/1639] 8368960: Adjust java UL logging in the build Reviewed-by: erikj, dholmes --- make/ToolsJdk.gmk | 2 +- make/autoconf/boot-jdk.m4 | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/make/ToolsJdk.gmk b/make/ToolsJdk.gmk index ae0dd069c80..629cadbf83a 100644 --- a/make/ToolsJdk.gmk +++ b/make/ToolsJdk.gmk @@ -63,7 +63,7 @@ TOOL_GENERATECURRENCYDATA = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_ TOOL_TZDB = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \ build.tools.tzdb.TzdbZoneRulesCompiler -TOOL_BLOCKED_CERTS = $(JAVA_SMALL) -Xlog:disable -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \ +TOOL_BLOCKED_CERTS = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \ --add-exports java.base/sun.security.util=ALL-UNNAMED \ build.tools.blockedcertsconverter.BlockedCertsConverter diff --git a/make/autoconf/boot-jdk.m4 b/make/autoconf/boot-jdk.m4 index 1dd768b2ae1..adc9afc349d 100644 --- a/make/autoconf/boot-jdk.m4 +++ b/make/autoconf/boot-jdk.m4 @@ -444,6 +444,9 @@ AC_DEFUN_ONCE([BOOTJDK_SETUP_BOOT_JDK_ARGUMENTS], # Force en-US environment UTIL_ADD_JVM_ARG_IF_OK([-Duser.language=en -Duser.country=US],boot_jdk_jvmargs,[$JAVA]) + UTIL_ADD_JVM_ARG_IF_OK([-Xlog:all=off:stdout],boot_jdk_jvmargs,[$JAVA]) + UTIL_ADD_JVM_ARG_IF_OK([-Xlog:all=warning:stderr],boot_jdk_jvmargs,[$JAVA]) + if test "x$BOOTJDK_USE_LOCAL_CDS" = xtrue; then # Use our own CDS archive UTIL_ADD_JVM_ARG_IF_OK([$boot_jdk_cds_args -Xshare:auto],boot_jdk_jvmargs,[$JAVA]) From d27649fe22a5bed9db72ac6c2595ac91f1fa28f8 Mon Sep 17 00:00:00 2001 From: Johannes Bechberger Date: Wed, 8 Oct 2025 08:03:32 +0000 Subject: [PATCH 0103/1639] 8367302: New test jdk/jfr/event/profiling/TestCPUTimeSampleQueueAutoSizes.java from JDK-8366082 is failing Reviewed-by: dholmes, apangin --- .../sampling/jfrCPUTimeThreadSampler.cpp | 23 +-- .../sampling/jfrCPUTimeThreadSampler.hpp | 7 +- src/hotspot/share/prims/whitebox.cpp | 16 +-- test/jdk/ProblemList-Xcomp.txt | 1 - .../TestCPUTimeSampleQueueAutoSizes.java | 131 +++++++++++------- test/lib/jdk/test/whitebox/WhiteBox.java | 5 +- 6 files changed, 92 insertions(+), 91 deletions(-) diff --git a/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.cpp b/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.cpp index 2ce1a93455b..7507b9c994e 100644 --- a/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.cpp +++ b/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.cpp @@ -230,8 +230,7 @@ class JfrCPUSamplerThread : public NonJavaThread { volatile bool _is_async_processing_of_cpu_time_jfr_requests_triggered; volatile bool _warned_about_timer_creation_failure; volatile bool _signal_handler_installed; - DEBUG_ONLY(volatile bool _out_of_stack_walking_enabled;) - DEBUG_ONLY(volatile u8 _out_of_stack_walking_iterations;) + DEBUG_ONLY(volatile bool _out_of_stack_walking_enabled = true;) static const u4 STOP_SIGNAL_BIT = 0x80000000; @@ -283,10 +282,6 @@ public: void set_out_of_stack_walking_enabled(bool runnable) { AtomicAccess::release_store(&_out_of_stack_walking_enabled, runnable); } - - u8 out_of_stack_walking_iterations() const { - return AtomicAccess::load(&_out_of_stack_walking_iterations); - } #endif }; @@ -394,7 +389,6 @@ void JfrCPUSamplerThread::run() { } DEBUG_ONLY(if (AtomicAccess::load_acquire(&_out_of_stack_walking_enabled)) {) if (AtomicAccess::cmpxchg(&_is_async_processing_of_cpu_time_jfr_requests_triggered, true, false)) { - DEBUG_ONLY(AtomicAccess::inc(&_out_of_stack_walking_iterations);) stackwalk_threads_in_native(); } DEBUG_ONLY(}) @@ -588,18 +582,14 @@ void JfrCPUTimeThreadSampling::handle_timer_signal(siginfo_t* info, void* contex } #ifdef ASSERT -void JfrCPUTimeThreadSampling::set_out_of_stack_walking_enabled(bool runnable) { +bool JfrCPUTimeThreadSampling::set_out_of_stack_walking_enabled(bool runnable) { if (_instance != nullptr && _instance->_sampler != nullptr) { _instance->_sampler->set_out_of_stack_walking_enabled(runnable); + return true; + } else { + return false; } } - -u8 JfrCPUTimeThreadSampling::out_of_stack_walking_iterations() { - if (_instance != nullptr && _instance->_sampler != nullptr) { - return _instance->_sampler->out_of_stack_walking_iterations(); - } - return 0; -} #endif void JfrCPUSamplerThread::sample_thread(JfrSampleRequest& request, void* ucontext, JavaThread* jt, JfrThreadLocal* tl, JfrTicks& now) { @@ -872,8 +862,9 @@ void JfrCPUTimeThreadSampling::on_javathread_terminate(JavaThread* thread) { } #ifdef ASSERT -static void set_out_of_stack_walking_enabled(bool runnable) { +bool JfrCPUTimeThreadSampling::set_out_of_stack_walking_enabled(bool runnable) { warn(); + return false; } #endif diff --git a/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.hpp b/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.hpp index e17e63fc3ed..e7c915fc8be 100644 --- a/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.hpp +++ b/src/hotspot/share/jfr/periodic/sampling/jfrCPUTimeThreadSampler.hpp @@ -139,9 +139,7 @@ class JfrCPUTimeThreadSampling : public JfrCHeapObj { static void trigger_async_processing_of_cpu_time_jfr_requests(); - DEBUG_ONLY(static void set_out_of_stack_walking_enabled(bool runnable);) - - DEBUG_ONLY(static u8 out_of_stack_walking_iterations();) + DEBUG_ONLY(static bool set_out_of_stack_walking_enabled(bool runnable);) }; #else @@ -162,8 +160,7 @@ private: static void on_javathread_create(JavaThread* thread); static void on_javathread_terminate(JavaThread* thread); - DEBUG_ONLY(static void set_out_of_stack_walking_enabled(bool runnable)); - DEBUG_ONLY(static u8 out_of_stack_walking_iterations();) + DEBUG_ONLY(static bool set_out_of_stack_walking_enabled(bool runnable)); }; #endif // defined(LINUX) diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp index 1ecd105f218..b4d100341e0 100644 --- a/src/hotspot/share/prims/whitebox.cpp +++ b/src/hotspot/share/prims/whitebox.cpp @@ -2710,7 +2710,7 @@ WB_ENTRY(void, WB_WaitUnsafe(JNIEnv* env, jobject wb, jint time)) os::naked_short_sleep(time); WB_END -WB_ENTRY(void, WB_BusyWait(JNIEnv* env, jobject wb, jint time)) +WB_ENTRY(void, WB_BusyWaitCPUTime(JNIEnv* env, jobject wb, jint time)) ThreadToNativeFromVM ttn(thread); u8 start = os::current_thread_cpu_time(); u8 target_duration = time * (u8)1000000; @@ -2721,21 +2721,12 @@ WB_END WB_ENTRY(jboolean, WB_CPUSamplerSetOutOfStackWalking(JNIEnv* env, jobject wb, jboolean enable)) #if defined(ASSERT) && INCLUDE_JFR && defined(LINUX) - JfrCPUTimeThreadSampling::set_out_of_stack_walking_enabled(enable == JNI_TRUE); - return JNI_TRUE; + return JfrCPUTimeThreadSampling::set_out_of_stack_walking_enabled(enable == JNI_TRUE) ? JNI_TRUE : JNI_FALSE; #else return JNI_FALSE; #endif WB_END -WB_ENTRY(jlong, WB_CPUSamplerOutOfStackWalkingIterations(JNIEnv* env, jobject wb)) - #if defined(ASSERT) && INCLUDE_JFR && defined(LINUX) - return (jlong)JfrCPUTimeThreadSampling::out_of_stack_walking_iterations(); - #else - return 0; - #endif -WB_END - WB_ENTRY(jstring, WB_GetLibcName(JNIEnv* env, jobject o)) ThreadToNativeFromVM ttn(thread); jstring info_string = env->NewStringUTF(XSTR(LIBC)); @@ -3092,9 +3083,8 @@ static JNINativeMethod methods[] = { {CC"isJVMTIIncluded", CC"()Z", (void*)&WB_IsJVMTIIncluded}, {CC"waitUnsafe", CC"(I)V", (void*)&WB_WaitUnsafe}, - {CC"busyWait", CC"(I)V", (void*)&WB_BusyWait}, + {CC"busyWaitCPUTime", CC"(I)V", (void*)&WB_BusyWaitCPUTime}, {CC"cpuSamplerSetOutOfStackWalking", CC"(Z)Z", (void*)&WB_CPUSamplerSetOutOfStackWalking}, - {CC"cpuSamplerOutOfStackWalkingIterations", CC"()J",(void*)&WB_CPUSamplerOutOfStackWalkingIterations}, {CC"getLibcName", CC"()Ljava/lang/String;", (void*)&WB_GetLibcName}, {CC"pinObject", CC"(Ljava/lang/Object;)V", (void*)&WB_PinObject}, diff --git a/test/jdk/ProblemList-Xcomp.txt b/test/jdk/ProblemList-Xcomp.txt index 8e37e6e15d0..5ed171a1fea 100644 --- a/test/jdk/ProblemList-Xcomp.txt +++ b/test/jdk/ProblemList-Xcomp.txt @@ -29,4 +29,3 @@ java/lang/invoke/MethodHandles/CatchExceptionTest.java 8146623 generic-all java/lang/reflect/callerCache/ReflectionCallerCacheTest.java 8332028 generic-all -jdk/jfr/event/profiling/TestCPUTimeSampleQueueAutoSizes.java 8367302 linux-all diff --git a/test/jdk/jdk/jfr/event/profiling/TestCPUTimeSampleQueueAutoSizes.java b/test/jdk/jdk/jfr/event/profiling/TestCPUTimeSampleQueueAutoSizes.java index 1ea96e3bad3..819329aabf5 100644 --- a/test/jdk/jdk/jfr/event/profiling/TestCPUTimeSampleQueueAutoSizes.java +++ b/test/jdk/jdk/jfr/event/profiling/TestCPUTimeSampleQueueAutoSizes.java @@ -24,6 +24,7 @@ package jdk.jfr.event.profiling; import java.time.Duration; +import java.time.Instant; import java.util.ArrayList; import java.util.Comparator; import java.util.stream.Collectors; @@ -41,8 +42,15 @@ import jdk.test.whitebox.WhiteBox; /* * Tests the sample queues increase in size as needed, when loss is recorded. + * + * The test starts CPU time sampling with a short interval (1ms), disabling + * out-of-stack sample processing for the duration of the test. + * It now runs in native for one second, to cause queue overflows, + * then it comes back into Java to trigger the queue walking. + * Repeats the cycle 5 times and verifies that the loss decreases from the first + * to the last iteration. * @test - * @requires vm.hasJFR & os.family == "linux" & vm.debug + * @requires vm.hasJFR & os.family == "linux" & vm.debug & vm.flagless * @library /test/lib * @modules jdk.jfr/jdk.jfr.internal * @build jdk.test.whitebox.WhiteBox @@ -54,15 +62,13 @@ public class TestCPUTimeSampleQueueAutoSizes { private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); - private static final String BURST_THREAD_NAME = "Burst-Thread-1"; - - static volatile boolean alive = true; - record LossEvent(long relativeTimeMillis, long lostSamples) {} /** A data collection from the CPUTimeSampleLost events for the burst thread */ static class LossEventCollection { private final List events = new ArrayList<>(); + private final List sampleEventsInTimeBox = new ArrayList<>(); + private final List timeBoxEnds = new ArrayList<>(); public synchronized void addEvent(LossEvent event) { events.add(event); @@ -74,81 +80,100 @@ public class TestCPUTimeSampleQueueAutoSizes { .collect(Collectors.toList()); } - public List getEventsPerInterval(long widthMillis, long stopTimeMillis) { + public synchronized List getEventsPerTimeBox() { List ret = new ArrayList<>(); - for (long start = 0; start < stopTimeMillis; start += widthMillis) { - long actualStart = Math.min(start, stopTimeMillis - widthMillis); + AtomicLong previousEnd = new AtomicLong(0); + for (Long timeBoxEnd : timeBoxEnds) { long lostSamples = events.stream() - .filter(e -> e.relativeTimeMillis >= actualStart && e.relativeTimeMillis < actualStart + widthMillis) + .filter(e -> e.relativeTimeMillis >= previousEnd.get() && e.relativeTimeMillis <= timeBoxEnd) .mapToLong(e -> e.lostSamples) .sum(); - ret.add(new LossEvent(actualStart, lostSamples)); + ret.add(new LossEvent(previousEnd.get(), lostSamples)); + previousEnd.set(timeBoxEnd); } return ret; } + public synchronized void addTimeBoxEnd(long timeBoxEnd, long sampleEvents) { + timeBoxEnds.add(timeBoxEnd); + sampleEventsInTimeBox.add(sampleEvents); + } + + public synchronized void print() { + System.out.println("Loss event information:"); + for (int i = 0; i < timeBoxEnds.size(); i++) { + System.out.println(" Time box end: " + timeBoxEnds.get(i) + ", sample events: " + sampleEventsInTimeBox.get(i)); + } + for (LossEvent e : events) { + System.out.println(" Lost samples event: " + e.lostSamples + " at " + e.relativeTimeMillis); + } + for (LossEvent e : getEventsPerTimeBox()) { + System.out.println(" Lost samples in time box ending at " + e.relativeTimeMillis + ": " + e.lostSamples); + } + } } public static void main(String[] args) throws Exception { try (RecordingStream rs = new RecordingStream()) { // setup recording - AtomicLong firstSampleTimeMillis = new AtomicLong(0); - AtomicLong lastSampleTimeMillis = new AtomicLong(0); + long burstThreadId = Thread.currentThread().threadId(); + final long startTimeMillis = Instant.now().toEpochMilli(); LossEventCollection lossEvents = new LossEventCollection(); + AtomicLong sampleEventCountInTimeBox = new AtomicLong(0); rs.enable(EventNames.CPUTimeSample).with("throttle", "1ms"); - rs.onEvent(EventNames.CPUTimeSample, e -> { - if (firstSampleTimeMillis.get() == 0 && e.getThread("eventThread").getJavaName().equals(BURST_THREAD_NAME)) { - firstSampleTimeMillis.set(e.getStartTime().toEpochMilli()); - } - if (e.getThread("eventThread").getJavaName().equals(BURST_THREAD_NAME)) { - lastSampleTimeMillis.set(e.getStartTime().toEpochMilli()); - } - }); rs.enable(EventNames.CPUTimeSamplesLost); rs.onEvent(EventNames.CPUTimeSamplesLost, e -> { - if (e.getThread("eventThread").getJavaName().equals(BURST_THREAD_NAME)) { + if (e.getThread("eventThread").getJavaThreadId() == burstThreadId) { long eventTime = e.getStartTime().toEpochMilli(); - long relativeTime = firstSampleTimeMillis.get() > 0 ? (eventTime - firstSampleTimeMillis.get()) : eventTime; - System.out.println("Lost samples: " + e.getLong("lostSamples") + " at " + relativeTime); + long relativeTime = eventTime - startTimeMillis; + System.out.println("Lost samples: " + e.getLong("lostSamples") + " at " + relativeTime + " start time " + startTimeMillis); lossEvents.addEvent(new LossEvent(relativeTime, e.getLong("lostSamples"))); } }); - WHITE_BOX.cpuSamplerSetOutOfStackWalking(false); + rs.onEvent(EventNames.CPUTimeSample, e -> { + if (e.getThread("eventThread").getJavaThreadId() == burstThreadId) { + sampleEventCountInTimeBox.incrementAndGet(); + } + }); rs.startAsync(); - // this thread runs all along - Thread burstThread = new Thread(() -> WHITE_BOX.busyWait(11000)); - burstThread.setName(BURST_THREAD_NAME); - burstThread.start(); - // now we toggle out-of-stack-walking off, wait 1 second and then turn it on for 500ms a few times + // we disable the out-of-stack walking so that the queue fills up and overflows + // while we are in native code + disableOutOfStackWalking(); + + for (int i = 0; i < 5; i++) { - boolean supported = WHITE_BOX.cpuSamplerSetOutOfStackWalking(false); - if (!supported) { - System.out.println("Out-of-stack-walking not supported, skipping test"); - Asserts.assertFalse(true); - return; - } - Thread.sleep(700); - long iterations = WHITE_BOX.cpuSamplerOutOfStackWalkingIterations(); - WHITE_BOX.cpuSamplerSetOutOfStackWalking(true); - Thread.sleep(300); - while (WHITE_BOX.cpuSamplerOutOfStackWalkingIterations() == iterations) { - Thread.sleep(50); // just to make sure the stack walking really ran - } + // run in native for one second + WHITE_BOX.busyWaitCPUTime(1000); + // going out-of-native at the end of the previous call should have triggered + // the safepoint handler, thereby also triggering the stack walking and creation + // of the loss event + WHITE_BOX.forceSafepoint(); // just to be sure + lossEvents.addTimeBoxEnd(Instant.now().toEpochMilli() - startTimeMillis, sampleEventCountInTimeBox.get()); + sampleEventCountInTimeBox.set(0); } + + rs.stop(); rs.close(); - checkThatLossDecreased(lossEvents, lastSampleTimeMillis.get() - firstSampleTimeMillis.get()); + + enableOutOfStackWalking(); + + checkThatLossDecreased(lossEvents); } } - static void checkThatLossDecreased(LossEventCollection lossEvents, long lastSampleTimeMillis) { - List intervalLosses = lossEvents.getEventsPerInterval(1000, lastSampleTimeMillis); - for (LossEvent interval : intervalLosses) { - System.out.println("Lost samples in interval " + interval.relativeTimeMillis + ": " + interval.lostSamples); - } - // check that there are at least 3 intervals - Asserts.assertTrue(intervalLosses.size() > 2); - // check that the second to last interval has far fewer lost samples than the first - Asserts.assertTrue(intervalLosses.get(intervalLosses.size() - 2).lostSamples < - intervalLosses.get(0).lostSamples / 2); + static void disableOutOfStackWalking() { + Asserts.assertTrue(WHITE_BOX.cpuSamplerSetOutOfStackWalking(false), "Out-of-stack-walking not supported"); + } + + static void enableOutOfStackWalking() { + WHITE_BOX.cpuSamplerSetOutOfStackWalking(true); + } + + static void checkThatLossDecreased(LossEventCollection lossEvents) { + lossEvents.print(); + List timeBoxedLosses = lossEvents.getEventsPerTimeBox(); + // check that the last time box has far fewer lost samples than the first + Asserts.assertTrue(timeBoxedLosses.get(timeBoxedLosses.size() - 1).lostSamples <= + timeBoxedLosses.get(0).lostSamples / 2); } } diff --git a/test/lib/jdk/test/whitebox/WhiteBox.java b/test/lib/jdk/test/whitebox/WhiteBox.java index 669ec48b619..d07dedd2a8c 100644 --- a/test/lib/jdk/test/whitebox/WhiteBox.java +++ b/test/lib/jdk/test/whitebox/WhiteBox.java @@ -847,13 +847,12 @@ public class WhiteBox { public native void waitUnsafe(int time_ms); - public native void busyWait(int cpuTimeMs); + public native void busyWaitCPUTime(int cpuTimeMs); + // returns true if supported, false if not public native boolean cpuSamplerSetOutOfStackWalking(boolean enable); - public native long cpuSamplerOutOfStackWalkingIterations(); - public native void pinObject(Object o); public native void unpinObject(Object o); From f58e17fd27e868e4a8816befc4c4bb8946c1f7fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ant=C3=B3n=20Seoane=20Ampudia?= Date: Wed, 8 Oct 2025 08:58:58 +0000 Subject: [PATCH 0104/1639] 8368780: IGV: Upgrade to Netbeans Platform 27 Reviewed-by: rcastanedalo, chagedorn --- src/utils/IdealGraphVisualizer/Filter/pom.xml | 4 ++-- src/utils/IdealGraphVisualizer/README.md | 2 +- src/utils/IdealGraphVisualizer/pom.xml | 12 ++++++++---- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/utils/IdealGraphVisualizer/Filter/pom.xml b/src/utils/IdealGraphVisualizer/Filter/pom.xml index 176f7a80180..c22ce274493 100644 --- a/src/utils/IdealGraphVisualizer/Filter/pom.xml +++ b/src/utils/IdealGraphVisualizer/Filter/pom.xml @@ -1,6 +1,6 @@ x << 64 = x << 0 = x (!= 2x << 63, for example for x = 1) + // According to the Java spec, chapter 15.19, we only consider the six lowest-order bits of the right-hand operand + // (i.e. "right-hand operand" & 0b111111). Therefore, x << 64 is the same as x << 0 (64 = 0b10000000 & 0b0111111 = 0). + return LShiftNode::make(add1->in(1), phase->intcon(con + 1), bt); } // Left input is an add of a constant? - const TypeInt *t12 = phase->type(add1->in(2))->isa_int(); - if( t12 && t12->is_con() ){ // Left input is an add of a con? + const TypeInteger* t12 = phase->type(add1->in(2))->isa_integer(bt); + if (t12 != nullptr && t12->is_con()) { // Left input is an add of a con? // Compute X << con0 - Node *lsh = phase->transform( new LShiftINode( add1->in(1), in(2) ) ); + Node* lsh = phase->transform(LShiftNode::make(add1->in(1), in(2), bt)); // Compute X<intcon(t12->get_con() << con)); + return AddNode::make(lsh, phase->integercon(java_shift_left(t12->get_con_as_long(bt), con, bt), bt), bt); } } } // Check for "(x >> C1) << C2" - if (add1_op == Op_RShiftI || add1_op == Op_URShiftI) { + if (add1_op == Op_RShift(bt) || add1_op == Op_URShift(bt)) { int add1Con = 0; const_shift_count(phase, add1, &add1Con); // Special case C1 == C2, which just masks off low bits - if (add1Con > 0 && con == add1Con) { + if (add1Con > 0 && con == (uint)add1Con) { // Convert to "(x & -(1 << C2))" - return new AndINode(add1->in(1), phase->intcon(java_negate(jint(1 << con)))); + return MulNode::make_and(add1->in(1), phase->integercon(java_negate(java_shift_left(1, con, bt), bt), bt), bt); } else { // Wait until the right shift has been sharpened to the correct count - if (add1Con > 0 && add1Con < BitsPerJavaInteger) { + if (add1Con > 0 && (uint)add1Con < bits_per_java_integer(bt)) { // As loop parsing can produce LShiftI nodes, we should wait until the graph is fully formed // to apply optimizations, otherwise we can inadvertently stop vectorization opportunities. if (phase->is_IterGVN()) { - if (con > add1Con) { + if (con > (uint)add1Con) { // Creates "(x << (C2 - C1)) & -(1 << C2)" - Node* lshift = phase->transform(new LShiftINode(add1->in(1), phase->intcon(con - add1Con))); - return new AndINode(lshift, phase->intcon(java_negate(jint(1 << con)))); + Node* lshift = phase->transform(LShiftNode::make(add1->in(1), phase->intcon(con - add1Con), bt)); + return MulNode::make_and(lshift, phase->integercon(java_negate(java_shift_left(1, con, bt), bt), bt), bt); } else { - assert(con < add1Con, "must be (%d < %d)", con, add1Con); + assert(con < (uint)add1Con, "must be (%d < %d)", con, add1Con); // Creates "(x >> (C1 - C2)) & -(1 << C2)" // Handle logical and arithmetic shifts Node* rshift; - if (add1_op == Op_RShiftI) { - rshift = phase->transform(new RShiftINode(add1->in(1), phase->intcon(add1Con - con))); + if (add1_op == Op_RShift(bt)) { + rshift = phase->transform(RShiftNode::make(add1->in(1), phase->intcon(add1Con - con), bt)); } else { - rshift = phase->transform(new URShiftINode(add1->in(1), phase->intcon(add1Con - con))); + rshift = phase->transform(URShiftNode::make(add1->in(1), phase->intcon(add1Con - con), bt)); } - return new AndINode(rshift, phase->intcon(java_negate(jint(1 << con)))); + return MulNode::make_and(rshift, phase->integercon(java_negate(java_shift_left(1, con, bt)), bt), bt); } } else { phase->record_for_igvn(this); @@ -1135,29 +1130,29 @@ Node *LShiftINode::Ideal(PhaseGVN *phase, bool can_reshape) { } // Check for "((x >> C1) & Y) << C2" - if (add1_op == Op_AndI) { - Node *add2 = add1->in(1); + if (add1_op == Op_And(bt)) { + Node* add2 = add1->in(1); int add2_op = add2->Opcode(); - if (add2_op == Op_RShiftI || add2_op == Op_URShiftI) { + if (add2_op == Op_RShift(bt) || add2_op == Op_URShift(bt)) { // Special case C1 == C2, which just masks off low bits if (add2->in(2) == in(2)) { // Convert to "(x & (Y << C2))" - Node* y_sh = phase->transform(new LShiftINode(add1->in(2), phase->intcon(con))); - return new AndINode(add2->in(1), y_sh); + Node* y_sh = phase->transform(LShiftNode::make(add1->in(2), phase->intcon(con), bt)); + return MulNode::make_and(add2->in(1), y_sh, bt); } int add2Con = 0; const_shift_count(phase, add2, &add2Con); - if (add2Con > 0 && add2Con < BitsPerJavaInteger) { + if (add2Con > 0 && (uint)add2Con < bits_per_java_integer(bt)) { if (phase->is_IterGVN()) { // Convert to "((x >> C1) << C2) & (Y << C2)" // Make "(x >> C1) << C2", which will get folded away by the rule above - Node* x_sh = phase->transform(new LShiftINode(add2, phase->intcon(con))); + Node* x_sh = phase->transform(LShiftNode::make(add2, phase->intcon(con), bt)); // Make "Y << C2", which will simplify when Y is a constant - Node* y_sh = phase->transform(new LShiftINode(add1->in(2), phase->intcon(con))); + Node* y_sh = phase->transform(LShiftNode::make(add1->in(2), phase->intcon(con), bt)); - return new AndINode(x_sh, y_sh); + return MulNode::make_and(x_sh, y_sh, bt); } else { phase->record_for_igvn(this); } @@ -1167,14 +1162,16 @@ Node *LShiftINode::Ideal(PhaseGVN *phase, bool can_reshape) { // Check for ((x & ((1<<(32-c0))-1)) << c0) which ANDs off high bits // before shifting them away. - const jint bits_mask = right_n_bits(BitsPerJavaInteger-con); - if( add1_op == Op_AndI && - phase->type(add1->in(2)) == TypeInt::make( bits_mask ) ) - return new LShiftINode( add1->in(1), in(2) ); + const jlong bits_mask = max_unsigned_integer(bt) >> con; + assert(bt != T_INT || bits_mask == right_n_bits(bits_per_java_integer(bt)-con), "inconsistent"); + if (add1_op == Op_And(bt) && + phase->type(add1->in(2)) == TypeInteger::make(bits_mask, bt)) { + return LShiftNode::make(add1->in(1), in(2), bt); + } - // Performs: + // Collapse nested left-shifts with constant rhs: // (X << con1) << con2 ==> X << (con1 + con2) - Node* doubleShift = collapse_nested_shift_left(phase, this, con, T_INT); + Node* doubleShift = collapse_nested_shift_left(phase, this, con, bt); if (doubleShift != nullptr) { return doubleShift; } @@ -1182,237 +1179,103 @@ Node *LShiftINode::Ideal(PhaseGVN *phase, bool can_reshape) { return nullptr; } -//------------------------------Value------------------------------------------ -// A LShiftINode shifts its input2 left by input1 amount. -const Type* LShiftINode::Value(PhaseGVN* phase) const { - const Type *t1 = phase->type( in(1) ); - const Type *t2 = phase->type( in(2) ); +//------------------------------Ideal------------------------------------------ +Node* LShiftINode::Ideal(PhaseGVN *phase, bool can_reshape) { + return IdealIL(phase, can_reshape, T_INT); +} + +const Type* LShiftNode::ValueIL(PhaseGVN* phase, BasicType bt) const { + const Type* t1 = phase->type(in(1)); + const Type* t2 = phase->type(in(2)); // Either input is TOP ==> the result is TOP - if( t1 == Type::TOP ) return Type::TOP; - if( t2 == Type::TOP ) return Type::TOP; + if (t1 == Type::TOP) { + return Type::TOP; + } + if (t2 == Type::TOP) { + return Type::TOP; + } // Left input is ZERO ==> the result is ZERO. - if( t1 == TypeInt::ZERO ) return TypeInt::ZERO; + if (t1 == TypeInteger::zero(bt)) { + return TypeInteger::zero(bt); + } // Shift by zero does nothing - if( t2 == TypeInt::ZERO ) return t1; + if (t2 == TypeInt::ZERO) { + return t1; + } // Either input is BOTTOM ==> the result is BOTTOM - if( (t1 == TypeInt::INT) || (t2 == TypeInt::INT) || - (t1 == Type::BOTTOM) || (t2 == Type::BOTTOM) ) - return TypeInt::INT; + if ((t1 == TypeInteger::bottom(bt)) || (t2 == TypeInt::INT) || + (t1 == Type::BOTTOM) || (t2 == Type::BOTTOM)) { + return TypeInteger::bottom(bt); + } - const TypeInt *r1 = t1->is_int(); // Handy access - const TypeInt *r2 = t2->is_int(); // Handy access + const TypeInteger* r1 = t1->is_integer(bt); // Handy access + const TypeInt* r2 = t2->is_int(); // Handy access - if (!r2->is_con()) - return TypeInt::INT; + if (!r2->is_con()) { + return TypeInteger::bottom(bt); + } uint shift = r2->get_con(); - shift &= BitsPerJavaInteger-1; // semantics of Java shifts - // Shift by a multiple of 32 does nothing: - if (shift == 0) return t1; + shift &= bits_per_java_integer(bt) - 1; // semantics of Java shifts + // Shift by a multiple of 32/64 does nothing: + if (shift == 0) { + return t1; + } // If the shift is a constant, shift the bounds of the type, // unless this could lead to an overflow. if (!r1->is_con()) { - jint lo = r1->_lo, hi = r1->_hi; - if (((lo << shift) >> shift) == lo && - ((hi << shift) >> shift) == hi) { - // No overflow. The range shifts up cleanly. - return TypeInt::make((jint)lo << (jint)shift, - (jint)hi << (jint)shift, - MAX2(r1->_widen,r2->_widen)); + jlong lo = r1->lo_as_long(), hi = r1->hi_as_long(); +#ifdef ASSERT + if (bt == T_INT) { + jint lo_int = r1->is_int()->_lo, hi_int = r1->is_int()->_hi; + assert((java_shift_right(java_shift_left(lo, shift, bt), shift, bt) == lo) == (((lo_int << shift) >> shift) == lo_int), "inconsistent"); + assert((java_shift_right(java_shift_left(hi, shift, bt), shift, bt) == hi) == (((hi_int << shift) >> shift) == hi_int), "inconsistent"); } - return TypeInt::INT; +#endif + if (java_shift_right(java_shift_left(lo, shift, bt), shift, bt) == lo && + java_shift_right(java_shift_left(hi, shift, bt), shift, bt) == hi) { + // No overflow. The range shifts up cleanly. + return TypeInteger::make(java_shift_left(lo, shift, bt), + java_shift_left(hi, shift, bt), + MAX2(r1->_widen, r2->_widen), bt); + } + return TypeInteger::bottom(bt); } - return TypeInt::make( (jint)r1->get_con() << (jint)shift ); + return TypeInteger::make(java_shift_left(r1->get_con_as_long(bt), shift, bt), bt); } -//============================================================================= -//------------------------------Identity--------------------------------------- -Node* LShiftLNode::Identity(PhaseGVN* phase) { +//------------------------------Value------------------------------------------ +const Type* LShiftINode::Value(PhaseGVN* phase) const { + return ValueIL(phase, T_INT); +} + +Node* LShiftNode::IdentityIL(PhaseGVN* phase, BasicType bt) { int count = 0; - if (const_shift_count(phase, this, &count) && (count & (BitsPerJavaLong - 1)) == 0) { - // Shift by a multiple of 64 does nothing + if (const_shift_count(phase, this, &count) && (count & (bits_per_java_integer(bt) - 1)) == 0) { + // Shift by a multiple of 32/64 does nothing return in(1); } return this; } +//============================================================================= +//------------------------------Identity--------------------------------------- +Node* LShiftLNode::Identity(PhaseGVN* phase) { + return IdentityIL(phase, T_LONG); +} + //------------------------------Ideal------------------------------------------ -// If the right input is a constant, and the left input is an add of a -// constant, flatten the tree: (X+con1)< X< X << (con1 + con2) -Node *LShiftLNode::Ideal(PhaseGVN *phase, bool can_reshape) { - int con = mask_and_replace_shift_amount(phase, this, BitsPerJavaLong); - if (con == 0) { - return nullptr; - } - - // Left input is an add? - Node *add1 = in(1); - int add1_op = add1->Opcode(); - if( add1_op == Op_AddL ) { // Left input is an add? - // Avoid dead data cycles from dead loops - assert( add1 != add1->in(1), "dead loop in LShiftLNode::Ideal" ); - - // Left input is an add of the same number? - if (con != (BitsPerJavaLong - 1) && add1->in(1) == add1->in(2)) { - // Convert "(x + x) << c0" into "x << (c0 + 1)" - // Can only be applied if c0 != 63 because: - // (x + x) << 63 = 2x << 63, while - // (x + x) << 63 --transform--> x << 64 = x << 0 = x (!= 2x << 63, for example for x = 1) - // According to the Java spec, chapter 15.19, we only consider the six lowest-order bits of the right-hand operand - // (i.e. "right-hand operand" & 0b111111). Therefore, x << 64 is the same as x << 0 (64 = 0b10000000 & 0b0111111 = 0). - return new LShiftLNode(add1->in(1), phase->intcon(con + 1)); - } - - // Left input is an add of a constant? - const TypeLong *t12 = phase->type(add1->in(2))->isa_long(); - if( t12 && t12->is_con() ){ // Left input is an add of a con? - // Compute X << con0 - Node *lsh = phase->transform( new LShiftLNode( add1->in(1), in(2) ) ); - // Compute X<longcon(t12->get_con() << con)); - } - } - - // Check for "(x >> C1) << C2" - if (add1_op == Op_RShiftL || add1_op == Op_URShiftL) { - int add1Con = 0; - const_shift_count(phase, add1, &add1Con); - - // Special case C1 == C2, which just masks off low bits - if (add1Con > 0 && con == add1Con) { - // Convert to "(x & -(1 << C2))" - return new AndLNode(add1->in(1), phase->longcon(java_negate(jlong(CONST64(1) << con)))); - } else { - // Wait until the right shift has been sharpened to the correct count - if (add1Con > 0 && add1Con < BitsPerJavaLong) { - // As loop parsing can produce LShiftI nodes, we should wait until the graph is fully formed - // to apply optimizations, otherwise we can inadvertently stop vectorization opportunities. - if (phase->is_IterGVN()) { - if (con > add1Con) { - // Creates "(x << (C2 - C1)) & -(1 << C2)" - Node* lshift = phase->transform(new LShiftLNode(add1->in(1), phase->intcon(con - add1Con))); - return new AndLNode(lshift, phase->longcon(java_negate(jlong(CONST64(1) << con)))); - } else { - assert(con < add1Con, "must be (%d < %d)", con, add1Con); - // Creates "(x >> (C1 - C2)) & -(1 << C2)" - - // Handle logical and arithmetic shifts - Node* rshift; - if (add1_op == Op_RShiftL) { - rshift = phase->transform(new RShiftLNode(add1->in(1), phase->intcon(add1Con - con))); - } else { - rshift = phase->transform(new URShiftLNode(add1->in(1), phase->intcon(add1Con - con))); - } - - return new AndLNode(rshift, phase->longcon(java_negate(jlong(CONST64(1) << con)))); - } - } else { - phase->record_for_igvn(this); - } - } - } - } - - // Check for "((x >> C1) & Y) << C2" - if (add1_op == Op_AndL) { - Node* add2 = add1->in(1); - int add2_op = add2->Opcode(); - if (add2_op == Op_RShiftL || add2_op == Op_URShiftL) { - // Special case C1 == C2, which just masks off low bits - if (add2->in(2) == in(2)) { - // Convert to "(x & (Y << C2))" - Node* y_sh = phase->transform(new LShiftLNode(add1->in(2), phase->intcon(con))); - return new AndLNode(add2->in(1), y_sh); - } - - int add2Con = 0; - const_shift_count(phase, add2, &add2Con); - if (add2Con > 0 && add2Con < BitsPerJavaLong) { - if (phase->is_IterGVN()) { - // Convert to "((x >> C1) << C2) & (Y << C2)" - - // Make "(x >> C1) << C2", which will get folded away by the rule above - Node* x_sh = phase->transform(new LShiftLNode(add2, phase->intcon(con))); - // Make "Y << C2", which will simplify when Y is a constant - Node* y_sh = phase->transform(new LShiftLNode(add1->in(2), phase->intcon(con))); - - return new AndLNode(x_sh, y_sh); - } else { - phase->record_for_igvn(this); - } - } - } - } - - // Check for ((x & ((CONST64(1)<<(64-c0))-1)) << c0) which ANDs off high bits - // before shifting them away. - const jlong bits_mask = jlong(max_julong >> con); - if( add1_op == Op_AndL && - phase->type(add1->in(2)) == TypeLong::make( bits_mask ) ) - return new LShiftLNode( add1->in(1), in(2) ); - - // Performs: - // (X << con1) << con2 ==> X << (con1 + con2) - Node* doubleShift = collapse_nested_shift_left(phase, this, con, T_LONG); - if (doubleShift != nullptr) { - return doubleShift; - } - - return nullptr; +Node* LShiftLNode::Ideal(PhaseGVN* phase, bool can_reshape) { + return IdealIL(phase, can_reshape, T_LONG); } //------------------------------Value------------------------------------------ -// A LShiftLNode shifts its input2 left by input1 amount. const Type* LShiftLNode::Value(PhaseGVN* phase) const { - const Type *t1 = phase->type( in(1) ); - const Type *t2 = phase->type( in(2) ); - // Either input is TOP ==> the result is TOP - if( t1 == Type::TOP ) return Type::TOP; - if( t2 == Type::TOP ) return Type::TOP; - - // Left input is ZERO ==> the result is ZERO. - if( t1 == TypeLong::ZERO ) return TypeLong::ZERO; - // Shift by zero does nothing - if( t2 == TypeInt::ZERO ) return t1; - - // Either input is BOTTOM ==> the result is BOTTOM - if( (t1 == TypeLong::LONG) || (t2 == TypeInt::INT) || - (t1 == Type::BOTTOM) || (t2 == Type::BOTTOM) ) - return TypeLong::LONG; - - const TypeLong *r1 = t1->is_long(); // Handy access - const TypeInt *r2 = t2->is_int(); // Handy access - - if (!r2->is_con()) - return TypeLong::LONG; - - uint shift = r2->get_con(); - shift &= BitsPerJavaLong - 1; // semantics of Java shifts - // Shift by a multiple of 64 does nothing: - if (shift == 0) return t1; - - // If the shift is a constant, shift the bounds of the type, - // unless this could lead to an overflow. - if (!r1->is_con()) { - jlong lo = r1->_lo, hi = r1->_hi; - if (((lo << shift) >> shift) == lo && - ((hi << shift) >> shift) == hi) { - // No overflow. The range shifts up cleanly. - return TypeLong::make((jlong)lo << (jint)shift, - (jlong)hi << (jint)shift, - MAX2(r1->_widen,r2->_widen)); - } - return TypeLong::LONG; - } - - return TypeLong::make( (jlong)r1->get_con() << (jint)shift ); + return ValueIL(phase, T_LONG); } RShiftNode* RShiftNode::make(Node* in1, Node* in2, BasicType bt) { @@ -1649,6 +1512,18 @@ const Type* RShiftLNode::Value(PhaseGVN* phase) const { return ValueIL(phase, T_LONG); } +URShiftNode* URShiftNode::make(Node* in1, Node* in2, BasicType bt) { + switch (bt) { + case T_INT: + return new URShiftINode(in1, in2); + case T_LONG: + return new URShiftLNode(in1, in2); + default: + fatal("Not implemented for %s", type2name(bt)); + } + return nullptr; +} + //============================================================================= //------------------------------Identity--------------------------------------- Node* URShiftINode::Identity(PhaseGVN* phase) { @@ -1684,7 +1559,7 @@ Node* URShiftINode::Identity(PhaseGVN* phase) { } //------------------------------Ideal------------------------------------------ -Node *URShiftINode::Ideal(PhaseGVN *phase, bool can_reshape) { +Node* URShiftINode::Ideal(PhaseGVN* phase, bool can_reshape) { int con = mask_and_replace_shift_amount(phase, this, BitsPerJavaInteger); if (con == 0) { return nullptr; @@ -1848,7 +1723,7 @@ Node* URShiftLNode::Identity(PhaseGVN* phase) { } //------------------------------Ideal------------------------------------------ -Node *URShiftLNode::Ideal(PhaseGVN *phase, bool can_reshape) { +Node* URShiftLNode::Ideal(PhaseGVN* phase, bool can_reshape) { int con = mask_and_replace_shift_amount(phase, this, BitsPerJavaLong); if (con == 0) { return nullptr; diff --git a/src/hotspot/share/opto/mulnode.hpp b/src/hotspot/share/opto/mulnode.hpp index b736c17b300..1e19e8ec5cd 100644 --- a/src/hotspot/share/opto/mulnode.hpp +++ b/src/hotspot/share/opto/mulnode.hpp @@ -260,10 +260,14 @@ inline Node* make_and(Node* a, Node* b) { class LShiftNode : public Node { public: - LShiftNode(Node *in1, Node *in2) : Node(nullptr,in1,in2) { + LShiftNode(Node* in1, Node* in2) : Node(nullptr,in1,in2) { init_class_id(Class_LShift); } + const Type* ValueIL(PhaseGVN* phase, BasicType bt) const; + Node* IdentityIL(PhaseGVN* phase, BasicType bt); + Node* IdealIL(PhaseGVN* phase, bool can_reshape, BasicType bt); + static LShiftNode* make(Node* in1, Node* in2, BasicType bt); }; @@ -271,12 +275,12 @@ public: // Logical shift left class LShiftINode : public LShiftNode { public: - LShiftINode(Node *in1, Node *in2) : LShiftNode(in1,in2) {} + LShiftINode(Node* in1, Node* in2) : LShiftNode(in1,in2) {} virtual int Opcode() const; virtual Node* Identity(PhaseGVN* phase); - virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); + virtual Node* Ideal(PhaseGVN *phase, bool can_reshape); virtual const Type* Value(PhaseGVN* phase) const; - const Type *bottom_type() const { return TypeInt::INT; } + const Type* bottom_type() const { return TypeInt::INT; } virtual uint ideal_reg() const { return Op_RegI; } }; @@ -287,9 +291,9 @@ public: LShiftLNode(Node *in1, Node *in2) : LShiftNode(in1,in2) {} virtual int Opcode() const; virtual Node* Identity(PhaseGVN* phase); - virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); + virtual Node* Ideal(PhaseGVN *phase, bool can_reshape); virtual const Type* Value(PhaseGVN* phase) const; - const Type *bottom_type() const { return TypeLong::LONG; } + const Type* bottom_type() const { return TypeLong::LONG; } virtual uint ideal_reg() const { return Op_RegL; } }; @@ -358,11 +362,17 @@ public: virtual uint ideal_reg() const { return Op_RegL; } }; +class URShiftNode : public Node { +public: + URShiftNode(Node* in1, Node* in2) : Node(nullptr, in1, in2) {} + static URShiftNode* make(Node* in1, Node* in2, BasicType bt); +}; + //------------------------------URShiftBNode----------------------------------- // Logical shift right -class URShiftBNode : public Node { +class URShiftBNode : public URShiftNode { public: - URShiftBNode( Node *in1, Node *in2 ) : Node(nullptr,in1,in2) { + URShiftBNode(Node* in1, Node* in2) : URShiftNode(in1,in2) { ShouldNotReachHere(); // only vector variant is used } virtual int Opcode() const; @@ -370,9 +380,9 @@ public: //------------------------------URShiftSNode----------------------------------- // Logical shift right -class URShiftSNode : public Node { +class URShiftSNode : public URShiftNode { public: - URShiftSNode( Node *in1, Node *in2 ) : Node(nullptr,in1,in2) { + URShiftSNode(Node* in1, Node* in2) : URShiftNode(in1,in2) { ShouldNotReachHere(); // only vector variant is used } virtual int Opcode() const; @@ -380,27 +390,27 @@ public: //------------------------------URShiftINode----------------------------------- // Logical shift right -class URShiftINode : public Node { +class URShiftINode : public URShiftNode { public: - URShiftINode( Node *in1, Node *in2 ) : Node(nullptr,in1,in2) {} + URShiftINode(Node* in1, Node* in2) : URShiftNode(in1,in2) {} virtual int Opcode() const; virtual Node* Identity(PhaseGVN* phase); - virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); + virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); virtual const Type* Value(PhaseGVN* phase) const; - const Type *bottom_type() const { return TypeInt::INT; } + const Type* bottom_type() const { return TypeInt::INT; } virtual uint ideal_reg() const { return Op_RegI; } }; //------------------------------URShiftLNode----------------------------------- // Logical shift right -class URShiftLNode : public Node { +class URShiftLNode : public URShiftNode { public: - URShiftLNode( Node *in1, Node *in2 ) : Node(nullptr,in1,in2) {} + URShiftLNode(Node* in1, Node* in2) : URShiftNode(in1,in2) {} virtual int Opcode() const; virtual Node* Identity(PhaseGVN* phase); - virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); + virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); virtual const Type* Value(PhaseGVN* phase) const; - const Type *bottom_type() const { return TypeLong::LONG; } + const Type* bottom_type() const { return TypeLong::LONG; } virtual uint ideal_reg() const { return Op_RegL; } }; diff --git a/src/hotspot/share/opto/node.hpp b/src/hotspot/share/opto/node.hpp index c2b3c4fb0ad..9ce9e705eec 100644 --- a/src/hotspot/share/opto/node.hpp +++ b/src/hotspot/share/opto/node.hpp @@ -2086,6 +2086,7 @@ Op_IL(Sub) Op_IL(Mul) Op_IL(URShift) Op_IL(LShift) +Op_IL(RShift) Op_IL(Xor) Op_IL(Cmp) Op_IL(Div) diff --git a/src/hotspot/share/utilities/globalDefinitions.hpp b/src/hotspot/share/utilities/globalDefinitions.hpp index 51ea80a0150..68900f8bc86 100644 --- a/src/hotspot/share/utilities/globalDefinitions.hpp +++ b/src/hotspot/share/utilities/globalDefinitions.hpp @@ -26,6 +26,7 @@ #define SHARE_UTILITIES_GLOBALDEFINITIONS_HPP #include "classfile_constants.h" +#include "utilities/checkedCast.hpp" #include "utilities/compilerWarnings.hpp" #include "utilities/debug.hpp" #include "utilities/forbiddenFunctions.hpp" @@ -1253,13 +1254,21 @@ JAVA_INTEGER_SHIFT_OP(>>, java_shift_right_unsigned, jlong, julong) #undef JAVA_INTEGER_SHIFT_OP +inline jlong java_negate(jlong v, BasicType bt) { + if (bt == T_INT) { + return java_negate(checked_cast(v)); + } + assert(bt == T_LONG, "int or long only"); + return java_negate(v); +} + // Some convenient bit shift operations that accepts a BasicType as the last // argument. These avoid potential mistakes with overloaded functions only // distinguished by lhs argument type. #define JAVA_INTEGER_SHIFT_BASIC_TYPE(FUNC) \ inline jlong FUNC(jlong lhs, jint rhs, BasicType bt) { \ if (bt == T_INT) { \ - return FUNC((jint) lhs, rhs); \ + return FUNC(checked_cast(lhs), rhs); \ } \ assert(bt == T_LONG, "unsupported basic type"); \ return FUNC(lhs, rhs); \ diff --git a/test/hotspot/jtreg/compiler/c2/irTests/LShiftINodeIdealizationTests.java b/test/hotspot/jtreg/compiler/c2/irTests/LShiftINodeIdealizationTests.java index 0b2a87fb2c5..7db56e2a878 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/LShiftINodeIdealizationTests.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/LShiftINodeIdealizationTests.java @@ -54,6 +54,17 @@ public class LShiftINodeIdealizationTests { "testDoubleShift9", "testDoubleShiftSliceAndStore", "testRandom", + "testShiftValue", + "testShiftValueOverflow", + "testShiftMultiple32", + "testShiftOfAddSameInput", + "testLargeShiftOfAddSameInput", + "testShiftOfAddConstant", + "testLShiftOfAndOfRShiftSameCon", + "testLShiftOfAndOfURShiftSameCon", + "testLShiftOfAndOfRShift", + "testLShiftOfAndOfURShift", + "testLShiftOfAndOfCon", }) public void runMethod() { int a = RunInfo.getRandom().nextInt(); @@ -71,6 +82,29 @@ public class LShiftINodeIdealizationTests { assertResult(d); assertResult(min); assertResult(max); + + Asserts.assertEQ(42 << 1, testShiftValue(42)); + Asserts.assertEQ(Integer.MAX_VALUE << 1, testShiftValueOverflow(Integer.MAX_VALUE)); + Asserts.assertEQ((Integer.MAX_VALUE-1) << 1, testShiftValueOverflow(Integer.MAX_VALUE-1)); + + assertResult(a, b); + assertResult(c, d); + assertResult(a, min); + assertResult(a, max); + assertResult(min, a); + assertResult(max, a); + assertResult(min, max); + assertResult(max, min); + assertResult(min, min); + assertResult(max, max); + } + + private void assertResult(int a, int b) { + otherInput = b; + Asserts.assertEQ(((a >> 4) & b) << 4, testLShiftOfAndOfRShiftSameCon(a)); + Asserts.assertEQ(((a >>> 4) & b) << 4, testLShiftOfAndOfURShiftSameCon(a)); + Asserts.assertEQ(((a >> 4) & b) << 8, testLShiftOfAndOfRShift(a)); + Asserts.assertEQ(((a >>> 4) & b) << 8, testLShiftOfAndOfURShift(a)); } @DontCompile @@ -83,6 +117,11 @@ public class LShiftINodeIdealizationTests { Asserts.assertEQ((a >>> 8) << 4, test6(a)); Asserts.assertEQ(((a >> 4) & 0xFF) << 8, test7(a)); Asserts.assertEQ(((a >>> 4) & 0xFF) << 8, test8(a)); + Asserts.assertEQ(a, testShiftMultiple32(a)); + Asserts.assertEQ((a + a) << 1, testShiftOfAddSameInput(a)); + Asserts.assertEQ((a + a) << 31, testLargeShiftOfAddSameInput(a)); + Asserts.assertEQ(((a + 1) << 1) + 1, testShiftOfAddConstant(a)); + Asserts.assertEQ((a & ((1 << (32 - 10)) -1)) << 10, testLShiftOfAndOfCon(a)); assertDoubleShiftResult(a); } @@ -267,4 +306,107 @@ public class LShiftINodeIdealizationTests { public int testRandom(int x) { return (x << CON0) << CON1; } + + @Test + @IR(counts = {IRNode.LSHIFT, "1"}, failOn = { IRNode.IF } ) + public int testShiftValue(int x) { + x = Integer.min(Integer.max(x, 10), 100); + int shift = x << 1; + if (shift > 200 || shift < 20) { + throw new RuntimeException("never taken"); + } + return shift; + } + + @Test + @IR(counts = {IRNode.LSHIFT, "1", IRNode.IF, "2" } ) + public int testShiftValueOverflow(int x) { + x = Integer.max(x, Integer.MAX_VALUE - 1); + int shift = x << 1; + if (shift != -2 && shift != -4) { + throw new RuntimeException("never taken"); + } + return shift; + } + + @Test + @IR(failOn = { IRNode.LSHIFT_I } ) + public int testShiftMultiple32(int x) { + return x << 128; + } + + @Test + @IR(counts = { IRNode.LSHIFT_I, "1" }, failOn = { IRNode.ADD_I } ) + public int testShiftOfAddSameInput(int x) { + return (x + x) << 1; + } + + @Test + @IR(counts = { IRNode.LSHIFT_I, "1", IRNode.ADD_I, "1" } ) + public int testLargeShiftOfAddSameInput(int x) { + return (x + x) << 31; + } + + @Test + @IR(counts = { IRNode.LSHIFT_I, "1", IRNode.ADD_I, "1" } ) + public int testShiftOfAddConstant(int x) { + return ((x + 1) << 1) + 1; + } + + static short shortField; + static byte byteField; + + @Test + @IR(counts = { IRNode.ADD_I, "1"} , failOn = { IRNode.LSHIFT_I, IRNode.RSHIFT_I } ) + @Arguments( values = { Argument.NUMBER_42 }) + public void testStoreShort(int x) { + shortField = (short)(x + x); + } + + @Test + @IR(counts = { IRNode.ADD_I, "1"} , failOn = { IRNode.LSHIFT_I, IRNode.RSHIFT_I } ) + @Arguments( values = { Argument.NUMBER_42 }) + public void testStoreByte(int x) { + byteField = (byte)(x + x); + } + + static int otherInput; + + @Test + @IR(counts = { IRNode.AND_I, "1", IRNode.LSHIFT_I, "1" } , failOn = { IRNode.RSHIFT_I } ) + public int testLShiftOfAndOfRShiftSameCon(int x) { + int shift = x >> 4; + int y = otherInput; + return (shift & y) << 4; + } + + @Test + @IR(counts = { IRNode.AND_I, "1", IRNode.LSHIFT_I, "1" } , failOn = { IRNode.URSHIFT_I } ) + public int testLShiftOfAndOfURShiftSameCon(int x) { + int shift = x >>> 4; + int y = otherInput; + return (shift & y) << 4; + } + + @Test + @IR(counts = { IRNode.AND_I, "2", IRNode.LSHIFT_I, "2" } , failOn = { IRNode.RSHIFT_I } ) + public int testLShiftOfAndOfRShift(int x) { + int shift = x >> 4; + int y = otherInput; + return (shift & y) << 8; + } + + @Test + @IR(counts = { IRNode.AND_I, "2", IRNode.LSHIFT_I, "2" } , failOn = { IRNode.URSHIFT_I } ) + public int testLShiftOfAndOfURShift(int x) { + int shift = x >>> 4; + int y = otherInput; + return (shift & y) << 8; + } + + @Test + @IR(counts = { IRNode.LSHIFT_I, "1" } , failOn = { IRNode.AND_I } ) + public int testLShiftOfAndOfCon(int x) { + return (x & ((1 << (32 - 10)) -1)) << 10; + } } diff --git a/test/hotspot/jtreg/compiler/c2/irTests/LShiftLNodeIdealizationTests.java b/test/hotspot/jtreg/compiler/c2/irTests/LShiftLNodeIdealizationTests.java index 11eb928d564..f489a348eef 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/LShiftLNodeIdealizationTests.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/LShiftLNodeIdealizationTests.java @@ -52,6 +52,17 @@ public class LShiftLNodeIdealizationTests { "testDoubleShift8", "testDoubleShift9", "testRandom", + "testShiftValue", + "testShiftValueOverflow", + "testShiftMultiple64", + "testShiftOfAddSameInput", + "testLargeShiftOfAddSameInput", + "testShiftOfAddConstant", + "testLShiftOfAndOfRShiftSameCon", + "testLShiftOfAndOfURShiftSameCon", + "testLShiftOfAndOfRShift", + "testLShiftOfAndOfURShift", + "testLShiftOfAndOfCon", }) public void runMethod() { long a = RunInfo.getRandom().nextLong(); @@ -69,6 +80,29 @@ public class LShiftLNodeIdealizationTests { assertResult(d); assertResult(min); assertResult(max); + + Asserts.assertEQ(42L << 1, testShiftValue(42)); + Asserts.assertEQ(Long.MAX_VALUE << 1, testShiftValueOverflow(Long.MAX_VALUE)); + Asserts.assertEQ((Long.MAX_VALUE-1) << 1, testShiftValueOverflow(Long.MAX_VALUE-1)); + + assertResult(a, b); + assertResult(c, d); + assertResult(a, min); + assertResult(a, max); + assertResult(min, a); + assertResult(max, a); + assertResult(min, max); + assertResult(max, min); + assertResult(min, min); + assertResult(max, max); + } + + private void assertResult(long a, long b) { + otherInput = b; + Asserts.assertEQ(((a >> 4) & b) << 4, testLShiftOfAndOfRShiftSameCon(a)); + Asserts.assertEQ(((a >>> 4) & b) << 4, testLShiftOfAndOfURShiftSameCon(a)); + Asserts.assertEQ(((a >> 4) & b) << 8, testLShiftOfAndOfRShift(a)); + Asserts.assertEQ(((a >>> 4) & b) << 8, testLShiftOfAndOfURShift(a)); } @DontCompile @@ -79,6 +113,11 @@ public class LShiftLNodeIdealizationTests { Asserts.assertEQ((a >>> 8L) << 4L, test6(a)); Asserts.assertEQ(((a >> 4L) & 0xFFL) << 8L, test7(a)); Asserts.assertEQ(((a >>> 4L) & 0xFFL) << 8L, test8(a)); + Asserts.assertEQ(a, testShiftMultiple64(a)); + Asserts.assertEQ((a + a) << 1, testShiftOfAddSameInput(a)); + Asserts.assertEQ((a + a) << 63, testLargeShiftOfAddSameInput(a)); + Asserts.assertEQ(((a + 1) << 1) + 1, testShiftOfAddConstant(a)); + Asserts.assertEQ((a & ((1L << (64 - 10)) -1)) << 10, testLShiftOfAndOfCon(a)); assertDoubleShiftResult(a); } @@ -233,4 +272,90 @@ public class LShiftLNodeIdealizationTests { public long testRandom(long x) { return (x << CON0) << CON1; } + + @Test + @IR(counts = {IRNode.LSHIFT, "1"}, failOn = { IRNode.IF } ) + public long testShiftValue(long x) { + x = Long.min(Long.max(x, 10), 100); + long shift = x << 1; + if (shift > 200 || shift < 20) { + throw new RuntimeException("never taken"); + } + return shift; + } + + @Test + @IR(counts = {IRNode.LSHIFT, "1", IRNode.IF, "2" } ) + public long testShiftValueOverflow(long x) { + x = Long.max(x, Long.MAX_VALUE - 1); + long shift = x << 1; + if (shift != -2 && shift != -4) { + throw new RuntimeException("never taken"); + } + return shift; + } + + @Test + @IR(failOn = { IRNode.LSHIFT_L } ) + public long testShiftMultiple64(long x) { + return x << 128; + } + + @Test + @IR(counts = { IRNode.LSHIFT_L, "1" }, failOn = { IRNode.ADD_L } ) + public long testShiftOfAddSameInput(long x) { + return (x + x) << 1; + } + + @Test + @IR(counts = { IRNode.LSHIFT_L, "1", IRNode.ADD_L, "1" } ) + public long testLargeShiftOfAddSameInput(long x) { + return (x + x) << 63; + } + + @Test + @IR(counts = { IRNode.LSHIFT_L, "1", IRNode.ADD_L, "1" } ) + public long testShiftOfAddConstant(long x) { + return ((x + 1) << 1) + 1; + } + + static long otherInput; + + @Test + @IR(counts = { IRNode.AND_L, "1", IRNode.LSHIFT_L, "1" } , failOn = { IRNode.RSHIFT_L } ) + public long testLShiftOfAndOfRShiftSameCon(long x) { + long shift = x >> 4; + long y = otherInput; + return (shift & y) << 4; + } + + @Test + @IR(counts = { IRNode.AND_L, "1", IRNode.LSHIFT_L, "1" } , failOn = { IRNode.URSHIFT_L } ) + public long testLShiftOfAndOfURShiftSameCon(long x) { + long shift = x >>> 4; + long y = otherInput; + return (shift & y) << 4; + } + + @Test + @IR(counts = { IRNode.AND_L, "2", IRNode.LSHIFT_L, "2" } , failOn = { IRNode.RSHIFT_L } ) + public long testLShiftOfAndOfRShift(long x) { + long shift = x >> 4; + long y = otherInput; + return (shift & y) << 8; + } + + @Test + @IR(counts = { IRNode.AND_L, "2", IRNode.LSHIFT_L, "2" } , failOn = { IRNode.URSHIFT_L } ) + public long testLShiftOfAndOfURShift(long x) { + long shift = x >>> 4; + long y = otherInput; + return (shift & y) << 8; + } + + @Test + @IR(counts = { IRNode.LSHIFT_L, "1" } , failOn = { IRNode.AND_L } ) + public long testLShiftOfAndOfCon(long x) { + return (x & ((1L << (64 - 10)) -1)) << 10; + } } From aed42a16bacb24753a536d07fedd736d64cde3be Mon Sep 17 00:00:00 2001 From: Artem Semenov Date: Thu, 16 Oct 2025 07:28:13 +0000 Subject: [PATCH 0227/1639] 8365609: Fix several potential NULL native pointer dereferences in the desktop module Found by Linux Verification Center (linuxtesting.org) with SVACE. Signed-off-by: Artem Semenov Artem Semenov Reviewed-by: azvegint, prr, serb --- .../share/native/libsplashscreen/splashscreen_gif.c | 4 +++- .../unix/native/libawt_xawt/awt/gtk3_interface.c | 5 +---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/java.desktop/share/native/libsplashscreen/splashscreen_gif.c b/src/java.desktop/share/native/libsplashscreen/splashscreen_gif.c index cbdad61f78e..4f2cfca8dd0 100644 --- a/src/java.desktop/share/native/libsplashscreen/splashscreen_gif.c +++ b/src/java.desktop/share/native/libsplashscreen/splashscreen_gif.c @@ -279,7 +279,9 @@ SplashDecodeGif(Splash * splash, GifFileType * gif) ImageRect dstRect; rgbquad_t fillColor = 0; // 0 is transparent - if (transparentColor < 0) { + if (colorMap && + colorMap->Colors && + transparentColor < 0) { fillColor= MAKE_QUAD_GIF( colorMap->Colors[gif->SBackGroundColor], 0xff); } diff --git a/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c b/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c index 916880873c6..e5b2dfa6db9 100644 --- a/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c +++ b/src/java.desktop/unix/native/libawt_xawt/awt/gtk3_interface.c @@ -276,10 +276,7 @@ GtkApi* gtk3_load(JNIEnv *env, const char* lib_name) fp_gtk_check_version = dl_symbol("gtk_check_version"); /* GLib */ - fp_glib_check_version = dlsym(gtk3_libhandle, "glib_check_version"); - if (!fp_glib_check_version) { - dlerror(); - } + fp_glib_check_version = dl_symbol("glib_check_version"); fp_g_free = dl_symbol("g_free"); fp_g_object_unref = dl_symbol("g_object_unref"); From ff6a0170f0ab5cfb4af6d6a4a779451823c486d6 Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Thu, 16 Oct 2025 07:35:41 +0000 Subject: [PATCH 0228/1639] 8369258: C2: enable ReassociateInvariants for all loop types Reviewed-by: epeter, qamai --- src/hotspot/share/opto/loopnode.cpp | 15 ++- .../loopopts/TestReassociateInvariants.java | 93 +++++++++++++++++++ ...MemorySegment_ReassociateInvariants1.java} | 15 +-- ...MemorySegment_ReassociateInvariants2.java} | 16 +--- 4 files changed, 108 insertions(+), 31 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/loopopts/TestReassociateInvariants.java rename test/hotspot/jtreg/compiler/loopopts/superword/{TestMemorySegment_8360204.java => TestMemorySegment_ReassociateInvariants1.java} (83%) rename test/hotspot/jtreg/compiler/loopopts/superword/{TestMemorySegment_8365982.java => TestMemorySegment_ReassociateInvariants2.java} (82%) diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp index 4cb1862cbb9..e8058edb4e5 100644 --- a/src/hotspot/share/opto/loopnode.cpp +++ b/src/hotspot/share/opto/loopnode.cpp @@ -5176,21 +5176,20 @@ void PhaseIdealLoop::build_and_optimize() { continue; } Node* head = lpt->_head; - if (!head->is_BaseCountedLoop() || !lpt->is_innermost()) continue; + if (!lpt->is_innermost()) continue; // check for vectorized loops, any reassociation of invariants was already done - if (head->is_CountedLoop()) { - if (head->as_CountedLoop()->is_unroll_only()) { - continue; - } else { - AutoNodeBudget node_budget(this); - lpt->reassociate_invariants(this); - } + if (head->is_CountedLoop() && head->as_CountedLoop()->is_unroll_only()) { + continue; + } else { + AutoNodeBudget node_budget(this); + lpt->reassociate_invariants(this); } // Because RCE opportunities can be masked by split_thru_phi, // look for RCE candidates and inhibit split_thru_phi // on just their loop-phi's for this pass of loop opts if (SplitIfBlocks && do_split_ifs && + head->is_BaseCountedLoop() && head->as_BaseCountedLoop()->is_valid_counted_loop(head->as_BaseCountedLoop()->bt()) && (lpt->policy_range_check(this, true, T_LONG) || (head->is_CountedLoop() && lpt->policy_range_check(this, true, T_INT)))) { diff --git a/test/hotspot/jtreg/compiler/loopopts/TestReassociateInvariants.java b/test/hotspot/jtreg/compiler/loopopts/TestReassociateInvariants.java new file mode 100644 index 00000000000..d03cb4e8567 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestReassociateInvariants.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2025 IBM Corporation. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8369258 + * @summary C2: enable ReassociateInvariants for all loop types + * @library /test/lib / + * @run driver compiler.loopopts.TestReassociateInvariants + */ + +package compiler.loopopts; + + +import compiler.lib.ir_framework.*; + +import java.util.Objects; + +public class TestReassociateInvariants { + private static long longStart = 0; + private static long longStop = 1000; + private static int intStart = 0; + private static int intStop = 1000; + + public static void main(String[] args) { + TestFramework.runWithFlags("-XX:-ShortRunningLongLoop"); + } + + // The IR framework is not powerful enough to directly check + // wether invariants are moved out of a loop so tests below rely on + // some side effect that can be observed by the IR framework. + + // Once a + (b + i) is transformed into i + (a + b), the a + b + // before the loop and the one from inside the loop common and one + // Add is removed. + @Test + @IR(counts = {IRNode.ADD_I, "3"}) + @Arguments(values = { Argument.NUMBER_42, Argument.NUMBER_42 }) + public int test1(int a, int b) { + int v = a + b; + for (int i = 1; i < 100; i *= 2) { + v += a + (b + i); + } + return v; + } + + // Range Check Elimination only happens once a + (b + i) is + // transformed into i + (a + b). With the range check eliminated, + // the loop can be removed. At this point, C2 doesn't support + // removal of long counted loop. The long counted loop is + // transformed into a loop nest with an inner int counted + // loop. That one is empty and is removed. + @Test + @IR(failOn = { IRNode.COUNTED_LOOP, IRNode.LONG_COUNTED_LOOP }) + @IR(counts = { IRNode.LOOP, "1" }) + @Arguments(values = { Argument.NUMBER_42, Argument.NUMBER_42 }) + public void test2(long a, long b) { + for (long i = longStart; i < longStop; i++) { + Objects.checkIndex(a + (b + i), Long.MAX_VALUE); + } + } + + // Same here for an int counted loop with long range checks + @Test + @IR(failOn = { IRNode.COUNTED_LOOP }) + @IR(counts = { IRNode.LOOP, "1" }) + @Arguments(values = { Argument.NUMBER_42, Argument.NUMBER_42 }) + public void test3(long a, long b) { + for (int i = intStart; i < intStop; i++) { + Objects.checkIndex(a + (b + i), Long.MAX_VALUE); + } + } +} diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegment_8360204.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegment_ReassociateInvariants1.java similarity index 83% rename from test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegment_8360204.java rename to test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegment_ReassociateInvariants1.java index ecefcec8afa..57864a09d69 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegment_8360204.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegment_ReassociateInvariants1.java @@ -31,16 +31,16 @@ import compiler.lib.ir_framework.*; /* * @test - * @bug 8324751 + * @bug 8324751 8369258 * @summary Reported issue: JDK-8360204: C2 SuperWord: missing RCE with MemorySegment.getAtIndex * The examples are generated from TestAliasingFuzzer.java * So if you see something change here, you may want to investigate if we * can also tighten up the IR rules there. * @library /test/lib / - * @run driver compiler.loopopts.superword.TestMemorySegment_8360204 + * @run driver compiler.loopopts.superword.TestMemorySegment_ReassociateInvariants1 */ -public class TestMemorySegment_8360204 { +public class TestMemorySegment_ReassociateInvariants1 { public static MemorySegment a = Arena.ofAuto().allocate(10_000); public static MemorySegment b = Arena.ofAuto().allocate(10_000); @@ -67,20 +67,13 @@ public class TestMemorySegment_8360204 { @Arguments(setup = "setup") @IR(counts = {IRNode.LOAD_VECTOR_I, "= 0", IRNode.STORE_VECTOR, "= 0", - ".*multiversion.*", "> 0"}, // Sadly, we now multiversion + ".*multiversion.*", "= 0"}, phase = CompilePhase.PRINT_IDEAL, applyIfPlatform = {"64-bit", "true"}, applyIf = {"AlignVector", "false"}, applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) - // There is no aliasing, so we should compile without multiversioning. - // But currently, there seems to be some issue with RCE, we peel and lose the predicate. - // Then we multiversion. // We could imagine that this would eventually vectorize, but since one counts up, and the other down, // we would have to implement shuffle first. - // - // If you see this IR rule fail: investigate JDK-8360204, possibly close it and fix this IR rule! - // Also: consider renaming the file to something more descriptive: what have you fixed with this? - // And: you may now be able to tighten IR rules in TestAliasingFuzzer.java public static void test(MemorySegment container_0, long invar0_0, MemorySegment container_1, long invar0_1, long ivLo, long ivHi) { for (long i = ivLo; i < ivHi; i+=1) { var v = container_0.getAtIndex(ValueLayout.JAVA_INT_UNALIGNED, 19125L + 1L * i + 1L * invar0_0 + 0L * invar0_1159 + 1L * invar1_1159); diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegment_8365982.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegment_ReassociateInvariants2.java similarity index 82% rename from test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegment_8365982.java rename to test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegment_ReassociateInvariants2.java index 65fd3861174..6f1590f5e19 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegment_8365982.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegment_ReassociateInvariants2.java @@ -31,16 +31,16 @@ import compiler.lib.ir_framework.*; /* * @test - * @bug 8324751 + * @bug 8324751 8369258 * @summary Reported issue: JDK-8365982: C2 SuperWord: missing RCE / strange Multiversioning with MemorySegment.set * The examples are generated from TestAliasingFuzzer.java * So if you see something change here, you may want to investigate if we * can also tighten up the IR rules there. * @library /test/lib / - * @run driver compiler.loopopts.superword.TestMemorySegment_8365982 + * @run driver compiler.loopopts.superword.TestMemorySegment_ReassociateInvariants2 */ -public class TestMemorySegment_8365982 { +public class TestMemorySegment_ReassociateInvariants2 { public static MemorySegment a = MemorySegment.ofArray(new short[100_000]); public static MemorySegment b = MemorySegment.ofArray(new short[100_000]); @@ -76,19 +76,11 @@ public class TestMemorySegment_8365982 { // @IR(counts = {IRNode.STORE_VECTOR, "> 0", IRNode.REPLICATE_S, "> 0", - ".*multiversion.*", "> 0"}, // Bad: Sadly, we now multiversion + ".*multiversion.*", "= 0"}, phase = CompilePhase.PRINT_IDEAL, applyIfPlatform = {"64-bit", "true"}, applyIfAnd = {"AlignVector", "false", "ShortRunningLongLoop", "true"}, applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) - // Some but not all predicates are RCE'd at the beginning. After unrolling, we multiversion (why?). - // After PreMainPost, we can do more RangeCheck. Now the main-loop of the multiversion_fast loop - // does not have any range checks any more. - // Now it vectorizes. That's good, but we should be able to vectorize without multiversioning. - // - // If you see this IR rule fail: investigate JDK-8365982, possibly close it and fix this IR rule! - // Also: consider renaming the file to something more descriptive: what have you fixed with this? - // And: you may now be able to tighten IR rules in TestAliasingFuzzer.java public static void test(MemorySegment container_0, long invar0_0, MemorySegment container_1, long invar0_1, long ivLo, long ivHi) { for (long i = ivHi-1; i >= ivLo; i-=1) { container_0.set(ValueLayout.JAVA_CHAR_UNALIGNED, -47143L + -2L * i + -2L * invar0_0 + -1L * invar0_853 + -1L * invar1_853 + 0L * invar2_853, (char)0x0102030405060708L); From 17c13e53aff16b294c7c0286ccb6ea3054b1de91 Mon Sep 17 00:00:00 2001 From: Christoph Langer Date: Thu, 16 Oct 2025 07:54:23 +0000 Subject: [PATCH 0229/1639] 8369683: Exclude runtime/Monitor/MonitorWithDeadObjectTest.java#DumpThreadsBeforeDetach on Alpine Linux debug Reviewed-by: mbaesken, dholmes --- .../jtreg/runtime/Monitor/MonitorWithDeadObjectTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/hotspot/jtreg/runtime/Monitor/MonitorWithDeadObjectTest.java b/test/hotspot/jtreg/runtime/Monitor/MonitorWithDeadObjectTest.java index 7f9b44a4a76..b1e6d0aa8c7 100644 --- a/test/hotspot/jtreg/runtime/Monitor/MonitorWithDeadObjectTest.java +++ b/test/hotspot/jtreg/runtime/Monitor/MonitorWithDeadObjectTest.java @@ -39,7 +39,8 @@ /* * @test id=DumpThreadsBeforeDetach - * @requires os.family != "windows" & os.family != "aix" + * @comment Temporarily exclude on Musl-C debug until JDK-8366133 is fixed. + * @requires os.family != "windows" & os.family != "aix" & (!vm.musl | !vm.debug) * @run main/othervm/native MonitorWithDeadObjectTest 1 */ From b5b83247da9caea30c88b69543e350783663bc46 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Thu, 16 Oct 2025 08:28:22 +0000 Subject: [PATCH 0230/1639] 8369656: Calling CompletableFuture.join() could execute task in common pool Reviewed-by: alanb, dl --- .../util/concurrent/CompletableFuture.java | 8 ++-- .../concurrent/tck/CompletableFutureTest.java | 43 +++++++++++++++++++ 2 files changed, 47 insertions(+), 4 deletions(-) diff --git a/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java b/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java index 7503c154ddb..1338f2fd804 100644 --- a/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java +++ b/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java @@ -1904,8 +1904,8 @@ public class CompletableFuture implements Future, CompletionStage { while ((r = result) == null) { if (q == null) { q = new Signaller(interruptible, 0L, 0L); - if (Thread.currentThread() instanceof ForkJoinWorkerThread) - ForkJoinPool.helpAsyncBlocker(defaultExecutor(), q); + if (Thread.currentThread() instanceof ForkJoinWorkerThread wt) + ForkJoinPool.helpAsyncBlocker(wt.pool, q); } else if (!queued) queued = tryPushStack(q); @@ -1950,8 +1950,8 @@ public class CompletableFuture implements Future, CompletionStage { break; else if (q == null) { q = new Signaller(true, nanos, deadline); - if (Thread.currentThread() instanceof ForkJoinWorkerThread) - ForkJoinPool.helpAsyncBlocker(defaultExecutor(), q); + if (Thread.currentThread() instanceof ForkJoinWorkerThread wt) + ForkJoinPool.helpAsyncBlocker(wt.pool, q); } else if (!queued) queued = tryPushStack(q); diff --git a/test/jdk/java/util/concurrent/tck/CompletableFutureTest.java b/test/jdk/java/util/concurrent/tck/CompletableFutureTest.java index de3d1dd1050..fc86936d5da 100644 --- a/test/jdk/java/util/concurrent/tck/CompletableFutureTest.java +++ b/test/jdk/java/util/concurrent/tck/CompletableFutureTest.java @@ -58,6 +58,7 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.Executor; import java.util.concurrent.ForkJoinPool; import java.util.concurrent.ForkJoinTask; +import java.util.concurrent.ForkJoinWorkerThread; import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; @@ -5133,4 +5134,46 @@ public class CompletableFutureTest extends JSR166TestCase { checkCompletedWithWrappedException(g.toCompletableFuture(), r.ex); r.assertInvoked(); }} + + public void testOnlyHelpsIfInTheSamePool() throws Exception { + class Logic { + interface Extractor { ForkJoinPool pool(CompletableFuture cf) throws Exception; } + static final List executeInnerOuter( + ForkJoinPool outer, ForkJoinPool inner, Logic.Extractor extractor + ) throws Exception { + return CompletableFuture.supplyAsync(() -> + Stream.iterate(1, i -> i + 1) + .limit(64) + .map(i -> CompletableFuture.supplyAsync( + () -> Thread.currentThread() instanceof ForkJoinWorkerThread wt ? wt.getPool() : null, inner) + ) + .map(cf -> { + try { + return extractor.pool(cf); + } catch (Exception ex) { + throw new AssertionError("Unexpected", ex); + } + }) + .toList() + , outer).join(); + } + } + + List extractors = + List.of( + c -> c.get(60, SECONDS), + CompletableFuture::get, + CompletableFuture::join + ); + + try (var pool = new ForkJoinPool(2)) { + for (var extractor : extractors) { + for (var p : Logic.executeInnerOuter(pool, ForkJoinPool.commonPool(), extractor)) + assertTrue(p != pool); // The inners should have all been executed by commonPool + + for (var p : Logic.executeInnerOuter(pool, pool, extractor)) + assertTrue(p == pool); // The inners could have been helped by the outer + } + } + } } From 6e911d819efa0f14ab1f9009b5bf325d99edb26c Mon Sep 17 00:00:00 2001 From: Martin Doerr Date: Thu, 16 Oct 2025 09:40:55 +0000 Subject: [PATCH 0231/1639] 8368205: [TESTBUG] VectorMaskCompareNotTest.java crashes when MaxVectorSize=8 Reviewed-by: dzhang, epeter, rrich --- .../vectorapi/VectorMaskCompareNotTest.java | 2 +- test/jtreg-ext/requires/VMProps.java | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/test/hotspot/jtreg/compiler/vectorapi/VectorMaskCompareNotTest.java b/test/hotspot/jtreg/compiler/vectorapi/VectorMaskCompareNotTest.java index 235093cceed..09185f63c69 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/VectorMaskCompareNotTest.java +++ b/test/hotspot/jtreg/compiler/vectorapi/VectorMaskCompareNotTest.java @@ -35,7 +35,7 @@ import jdk.test.lib.Asserts; * @library /test/lib / * @summary test combining vector not operation with compare * @modules jdk.incubator.vector - * @requires (os.arch != "riscv64" | (os.arch == "riscv64" & vm.cpu.features ~= ".*rvv.*")) + * @requires vm.opt.final.MaxVectorSize == "null" | vm.opt.final.MaxVectorSize >= 16 * * @run driver compiler.vectorapi.VectorMaskCompareNotTest */ diff --git a/test/jtreg-ext/requires/VMProps.java b/test/jtreg-ext/requires/VMProps.java index 29057f24d3b..3c06c97b37a 100644 --- a/test/jtreg-ext/requires/VMProps.java +++ b/test/jtreg-ext/requires/VMProps.java @@ -149,6 +149,7 @@ public class VMProps implements Callable> { vmGC(map); // vm.gc.X = true/false vmGCforCDS(map); // may set vm.gc vmOptFinalFlags(map); + vmOptFinalIntxFlags(map); dump(map.map); log("Leaving call()"); @@ -389,6 +390,26 @@ public class VMProps implements Callable> { vmOptFinalFlag(map, "UseVectorizedMismatchIntrinsic"); } + /** + * Selected final flag of type intx. + * + * @param map - property-value pairs + * @param flagName - flag name + */ + private void vmOptFinalIntxFlag(SafeMap map, String flagName) { + map.put("vm.opt.final." + flagName, + () -> String.valueOf(WB.getIntxVMFlag(flagName))); + } + + /** + * Selected sets of final flags of type intx. + * + * @param map - property-value pairs + */ + protected void vmOptFinalIntxFlags(SafeMap map) { + vmOptFinalIntxFlag(map, "MaxVectorSize"); + } + /** * @return "true" if VM has a serviceability agent. */ From d6c122b3ff1ccd559ba9c310976a77eefaf09ece Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Thu, 16 Oct 2025 09:57:11 +0000 Subject: [PATCH 0232/1639] 8369982: ProblemList jdk/jfr/jvm/TestWaste.java Reviewed-by: tschatzl, dholmes --- test/jdk/ProblemList.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index c305bc0bbeb..0e69446ae35 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -750,6 +750,7 @@ jdk/incubator/vector/LoadJsvmlTest.java 8305390 windows- jdk/jfr/event/compiler/TestCodeSweeper.java 8338127 generic-all jdk/jfr/event/oldobject/TestShenandoah.java 8342951 generic-all jdk/jfr/event/runtime/TestResidentSetSizeEvent.java 8309846 aix-ppc64 +jdk/jfr/jvm/TestWaste.java 8369949 generic-all ############################################################################ From ead35a754bf3a545a1b68f28d3d939750f11af39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Jeli=C5=84ski?= Date: Thu, 16 Oct 2025 11:05:13 +0000 Subject: [PATCH 0233/1639] 8358942: HttpClient adds Content-Length: 0 for a GET request with a BodyPublishers.noBody() Reviewed-by: dfuchs, vyazici --- .../jdk/internal/net/http/Http1Request.java | 11 +- .../httpclient/ContentLengthHeaderTest.java | 154 +++++++++++++++--- 2 files changed, 136 insertions(+), 29 deletions(-) diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/Http1Request.java b/src/java.net.http/share/classes/jdk/internal/net/http/Http1Request.java index 815b6bad20c..8d28b664036 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/Http1Request.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/Http1Request.java @@ -290,7 +290,8 @@ class Http1Request { } String uriString = requestURI(); StringBuilder sb = new StringBuilder(64); - sb.append(request.method()) + String method = request.method(); + sb.append(method) .append(' ') .append(uriString) .append(" HTTP/1.1\r\n"); @@ -300,11 +301,15 @@ class Http1Request { systemHeadersBuilder.setHeader("Host", hostString()); } - // GET, HEAD and DELETE with no request body should not set the Content-Length header if (requestPublisher != null) { contentLength = requestPublisher.contentLength(); if (contentLength == 0) { - systemHeadersBuilder.setHeader("Content-Length", "0"); + // PUT and POST with no request body should set the Content-Length header + // even when the content is empty. + // Other methods defined in RFC 9110 should not send the header in that case. + if ("POST".equals(method) || "PUT".equals(method)) { + systemHeadersBuilder.setHeader("Content-Length", "0"); + } } else if (contentLength > 0) { systemHeadersBuilder.setHeader("Content-Length", Long.toString(contentLength)); streaming = false; diff --git a/test/jdk/java/net/httpclient/ContentLengthHeaderTest.java b/test/jdk/java/net/httpclient/ContentLengthHeaderTest.java index f302de4ee48..d7c77d0690a 100644 --- a/test/jdk/java/net/httpclient/ContentLengthHeaderTest.java +++ b/test/jdk/java/net/httpclient/ContentLengthHeaderTest.java @@ -29,8 +29,9 @@ * @library /test/lib /test/jdk/java/net/httpclient/lib * @build jdk.test.lib.net.SimpleSSLContext * jdk.httpclient.test.lib.common.HttpServerAdapters - * @bug 8283544 + * @bug 8283544 8358942 * @run testng/othervm + * -Djdk.httpclient.allowRestrictedHeaders=content-length * -Djdk.internal.httpclient.debug=true * ContentLengthHeaderTest */ @@ -95,8 +96,8 @@ public class ContentLengthHeaderTest implements HttpServerAdapters { testContentLengthServerH2.addHandler(new NoContentLengthHandler(), NO_BODY_PATH); testContentLengthServerH3.addHandler(new NoContentLengthHandler(), NO_BODY_PATH); testContentLengthServerH1.addHandler(new ContentLengthHandler(), BODY_PATH); - testContentLengthServerH2.addHandler(new OptionalContentLengthHandler(), BODY_PATH); - testContentLengthServerH3.addHandler(new OptionalContentLengthHandler(), BODY_PATH); + testContentLengthServerH2.addHandler(new ContentLengthHandler(), BODY_PATH); + testContentLengthServerH3.addHandler(new ContentLengthHandler(), BODY_PATH); testContentLengthURIH1 = URIBuilder.newBuilder() .scheme("http") .loopback() @@ -163,6 +164,13 @@ public class ContentLengthHeaderTest implements HttpServerAdapters { }; } + @DataProvider(name = "h1body") + Object[][] h1body() { + return new Object[][]{ + {HTTP_1_1, URI.create(testContentLengthURIH1 + BODY_PATH)} + }; + } + @DataProvider(name = "nobodies") Object[][] nobodies() { return new Object[][]{ @@ -186,6 +194,35 @@ public class ContentLengthHeaderTest implements HttpServerAdapters { assertEquals(resp.version(), version); } + @Test(dataProvider = "nobodies") + // A GET request with empty request body should have no Content-length header + public void getWithEmptyBody(Version version, URI uri) throws IOException, InterruptedException { + testLog.println(version + " Checking GET with no request body"); + HttpRequest req = HttpRequest.newBuilder() + .version(version) + .method("GET", HttpRequest.BodyPublishers.noBody()) + .uri(uri) + .build(); + HttpResponse resp = hc.send(req, HttpResponse.BodyHandlers.ofString(UTF_8)); + assertEquals(resp.statusCode(), 200, resp.body()); + assertEquals(resp.version(), version); + } + + @Test(dataProvider = "bodies") + // A GET request with empty request body and explicitly added Content-length header + public void getWithZeroContentLength(Version version, URI uri) throws IOException, InterruptedException { + testLog.println(version + " Checking GET with no request body"); + HttpRequest req = HttpRequest.newBuilder() + .version(version) + .method("GET", HttpRequest.BodyPublishers.noBody()) + .header("Content-length", "0") + .uri(uri) + .build(); + HttpResponse resp = hc.send(req, HttpResponse.BodyHandlers.ofString(UTF_8)); + assertEquals(resp.statusCode(), 200, resp.body()); + assertEquals(resp.version(), version); + } + @Test(dataProvider = "bodies") // A GET request with a request body should have a Content-length header // in HTTP/1.1 @@ -215,6 +252,20 @@ public class ContentLengthHeaderTest implements HttpServerAdapters { assertEquals(resp.version(), version); } + @Test(dataProvider = "nobodies") + // A DELETE request with empty request body should have no Content-length header + public void deleteWithEmptyBody(Version version, URI uri) throws IOException, InterruptedException { + testLog.println(version + " Checking DELETE with no request body"); + HttpRequest req = HttpRequest.newBuilder() + .version(version) + .method("DELETE", HttpRequest.BodyPublishers.noBody()) + .uri(uri) + .build(); + HttpResponse resp = hc.send(req, HttpResponse.BodyHandlers.ofString(UTF_8)); + assertEquals(resp.statusCode(), 200, resp.body()); + assertEquals(resp.version(), version); + } + @Test(dataProvider = "bodies") // A DELETE request with a request body should have a Content-length header // in HTTP/1.1 @@ -244,6 +295,20 @@ public class ContentLengthHeaderTest implements HttpServerAdapters { assertEquals(resp.version(), version); } + @Test(dataProvider = "nobodies") + // A HEAD request with empty request body should have no Content-length header + public void headWithEmptyBody(Version version, URI uri) throws IOException, InterruptedException { + testLog.println(version + " Checking HEAD with no request body"); + HttpRequest req = HttpRequest.newBuilder() + .version(version) + .method("HEAD", HttpRequest.BodyPublishers.noBody()) + .uri(uri) + .build(); + HttpResponse resp = hc.send(req, HttpResponse.BodyHandlers.ofString(UTF_8)); + assertEquals(resp.statusCode(), 200, resp.body()); + assertEquals(resp.version(), version); + } + @Test(dataProvider = "bodies") // A HEAD request with a request body should have a Content-length header // in HTTP/1.1 @@ -261,6 +326,66 @@ public class ContentLengthHeaderTest implements HttpServerAdapters { assertEquals(resp.version(), version); } + @Test(dataProvider = "h1body") + // A POST request with empty request body should have a Content-length header + // in HTTP/1.1 + public void postWithEmptyBody(Version version, URI uri) throws IOException, InterruptedException { + testLog.println(version + " Checking POST with request body"); + HttpRequest req = HttpRequest.newBuilder() + .version(version) + .method("POST", HttpRequest.BodyPublishers.noBody()) + .uri(uri) + .build(); + HttpResponse resp = hc.send(req, HttpResponse.BodyHandlers.ofString(UTF_8)); + assertEquals(resp.statusCode(), 200, resp.body()); + assertEquals(resp.version(), version); + } + + @Test(dataProvider = "bodies") + // A POST request with a request body should have a Content-length header + // in HTTP/1.1 + public void postWithBody(Version version, URI uri) throws IOException, InterruptedException { + testLog.println(version + " Checking POST with request body"); + HttpRequest req = HttpRequest.newBuilder() + .version(version) + .POST(HttpRequest.BodyPublishers.ofString("POST Body")) + .uri(uri) + .build(); + HttpResponse resp = hc.send(req, HttpResponse.BodyHandlers.ofString(UTF_8)); + assertEquals(resp.statusCode(), 200, resp.body()); + assertEquals(resp.version(), version); + } + + @Test(dataProvider = "h1body") + // A PUT request with empty request body should have a Content-length header + // in HTTP/1.1 + public void putWithEmptyBody(Version version, URI uri) throws IOException, InterruptedException { + testLog.println(version + " Checking PUT with request body"); + HttpRequest req = HttpRequest.newBuilder() + .version(version) + .method("PUT", HttpRequest.BodyPublishers.noBody()) + .uri(uri) + .build(); + HttpResponse resp = hc.send(req, HttpResponse.BodyHandlers.ofString(UTF_8)); + assertEquals(resp.statusCode(), 200, resp.body()); + assertEquals(resp.version(), version); + } + + @Test(dataProvider = "bodies") + // A PUT request with a request body should have a Content-length header + // in HTTP/1.1 + public void putWithBody(Version version, URI uri) throws IOException, InterruptedException { + testLog.println(version + " Checking PUT with request body"); + HttpRequest req = HttpRequest.newBuilder() + .version(version) + .PUT(HttpRequest.BodyPublishers.ofString("PUT Body")) + .uri(uri) + .build(); + HttpResponse resp = hc.send(req, HttpResponse.BodyHandlers.ofString(UTF_8)); + assertEquals(resp.statusCode(), 200, resp.body()); + assertEquals(resp.version(), version); + } + public static void handleResponse(long expected, HttpTestExchange ex, String body, int rCode) throws IOException { try (InputStream is = ex.getRequestBody()) { byte[] reqBody = is.readAllBytes(); @@ -324,27 +449,4 @@ public class ContentLengthHeaderTest implements HttpServerAdapters { } } } - - /** - * A handler used for cases where the presence of a Content-Length - * header is optional. If present, its value must match the number of - * bytes sent in the request body. - */ - static class OptionalContentLengthHandler implements HttpTestHandler { - - @Override - public void handle(HttpTestExchange exchange) throws IOException { - testLog.println("OptionalContentLengthHandler: Received Headers " - + exchange.getRequestHeaders().entrySet() + - " from " + exchange.getRequestMethod() + " request."); - Optional contentLength = exchange.getRequestHeaders().firstValue("Content-Length"); - - // Check Content-length header was set - if (contentLength.isPresent()) { - handleResponse(Long.parseLong(contentLength.get()), exchange, "Request completed", 200); - } else { - handleResponse(-1, exchange, "Request completed, no content length", 200); - } - } - } } From 5fc3904bfe290625ed6cf9b41773b35b52bf72b7 Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Thu, 16 Oct 2025 11:16:05 +0000 Subject: [PATCH 0234/1639] 8369491: Temporarily revert default TIMEOUT_FACTOR back to 4 Reviewed-by: lkorinth, cstein, jpai, syan, serb, prr --- doc/testing.html | 2 +- doc/testing.md | 2 +- make/RunTests.gmk | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/testing.html b/doc/testing.html index 89a9b1b23b7..b9838735e4f 100644 --- a/doc/testing.html +++ b/doc/testing.html @@ -450,7 +450,7 @@ itself (-timeoutFactor). Also, some test cases that programmatically wait a certain amount of time will apply this factor. If we run in forced compilation mode (-Xcomp), the build system will automatically adjust this factor to compensate for less -performance. Defaults to 1.

    +performance. Defaults to 4.

    FAILURE_HANDLER_TIMEOUT

    Sets the argument -timeoutHandlerTimeout for JTReg. The default value is 0. This is only valid if the failure handler is diff --git a/doc/testing.md b/doc/testing.md index 324f9645c27..0144610a5bf 100644 --- a/doc/testing.md +++ b/doc/testing.md @@ -387,7 +387,7 @@ The `TIMEOUT_FACTOR` is forwarded to JTReg framework itself (`-timeoutFactor`). Also, some test cases that programmatically wait a certain amount of time will apply this factor. If we run in forced compilation mode (`-Xcomp`), the build system will automatically -adjust this factor to compensate for less performance. Defaults to 1. +adjust this factor to compensate for less performance. Defaults to 4. #### FAILURE_HANDLER_TIMEOUT diff --git a/make/RunTests.gmk b/make/RunTests.gmk index 7b05a0ba12f..947389f64f9 100644 --- a/make/RunTests.gmk +++ b/make/RunTests.gmk @@ -946,8 +946,8 @@ define SetupRunJtregTestBody JTREG_ALL_OPTIONS := $$(JTREG_JAVA_OPTIONS) $$(JTREG_VM_OPTIONS) JTREG_AUTO_PROBLEM_LISTS := - # Please reach consensus before changing this. It was not easy changing it to a `1`. - JTREG_AUTO_TIMEOUT_FACTOR := 1 + # Please reach consensus before changing this. + JTREG_AUTO_TIMEOUT_FACTOR := 4 ifneq ($$(findstring -Xcomp, $$(JTREG_ALL_OPTIONS)), ) JTREG_AUTO_PROBLEM_LISTS += ProblemList-Xcomp.txt From 1653999871c8d7b1e61b44f8525e09b2cd0bdb6b Mon Sep 17 00:00:00 2001 From: Yasumasa Suenaga Date: Thu, 16 Oct 2025 12:45:05 +0000 Subject: [PATCH 0235/1639] 8369505: jhsdb jstack cannot handle continuation stub Reviewed-by: cjplummer, pchilanomate --- .../share/runtime/continuationEntry.hpp | 1 + src/hotspot/share/runtime/vmStructs.cpp | 5 +- .../sun/jvm/hotspot/code/CodeBlob.java | 2 + .../hotspot/runtime/ContinuationEntry.java | 63 ++++++++++++++ .../sun/jvm/hotspot/runtime/JavaThread.java | 6 ++ .../hotspot/runtime/aarch64/AARCH64Frame.java | 18 +++- .../hotspot/runtime/riscv64/RISCV64Frame.java | 18 +++- .../sun/jvm/hotspot/runtime/x86/X86Frame.java | 18 +++- .../sa/LingeredAppWithVirtualThread.java | 87 +++++++++++++++++++ .../sa/TestJhsdbJstackWithVirtualThread.java | 83 ++++++++++++++++++ 10 files changed, 297 insertions(+), 4 deletions(-) create mode 100644 src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ContinuationEntry.java create mode 100644 test/hotspot/jtreg/serviceability/sa/LingeredAppWithVirtualThread.java create mode 100644 test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackWithVirtualThread.java diff --git a/src/hotspot/share/runtime/continuationEntry.hpp b/src/hotspot/share/runtime/continuationEntry.hpp index 8361f2f912b..490293f5b11 100644 --- a/src/hotspot/share/runtime/continuationEntry.hpp +++ b/src/hotspot/share/runtime/continuationEntry.hpp @@ -39,6 +39,7 @@ class RegisterMap; // Metadata stored in the continuation entry frame class ContinuationEntry { + friend class VMStructs; friend class JVMCIVMStructs; ContinuationEntryPD _pd; #ifdef ASSERT diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index dee0a5d4eb7..8dc4b660f91 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -616,6 +616,7 @@ nonstatic_field(JavaThread, _active_handles, JNIHandleBlock*) \ nonstatic_field(JavaThread, _monitor_owner_id, int64_t) \ volatile_nonstatic_field(JavaThread, _terminated, JavaThread::TerminatedTypes) \ + nonstatic_field(JavaThread, _cont_entry, ContinuationEntry*) \ nonstatic_field(Thread, _osthread, OSThread*) \ \ /************/ \ @@ -796,7 +797,8 @@ nonstatic_field(Mutex, _name, const char*) \ static_field(Mutex, _mutex_array, Mutex**) \ static_field(Mutex, _num_mutex, int) \ - volatile_nonstatic_field(Mutex, _owner, Thread*) + volatile_nonstatic_field(Mutex, _owner, Thread*) \ + static_field(ContinuationEntry, _return_pc, address) //-------------------------------------------------------------------------------- // VM_TYPES @@ -1270,6 +1272,7 @@ declare_toplevel_type(FileMapHeader) \ declare_toplevel_type(CDSFileMapRegion) \ declare_toplevel_type(UpcallStub::FrameData) \ + declare_toplevel_type(ContinuationEntry) \ \ /************/ \ /* GC types */ \ diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/CodeBlob.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/CodeBlob.java index 20c5fabf8bc..12469efc67e 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/CodeBlob.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/code/CodeBlob.java @@ -180,6 +180,8 @@ public class CodeBlob extends VMObject { public boolean isUpcallStub() { return getKind() == UpcallKind; } + public boolean isContinuationStub() { return getName().equals("StubRoutines (continuation stubs)"); } + public boolean isJavaMethod() { return false; } public boolean isNativeMethod() { return false; } diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ContinuationEntry.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ContinuationEntry.java new file mode 100644 index 00000000000..73152bdee84 --- /dev/null +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ContinuationEntry.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, NTT DATA. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +package sun.jvm.hotspot.runtime; + +import sun.jvm.hotspot.debugger.*; +import sun.jvm.hotspot.runtime.*; +import sun.jvm.hotspot.types.*; + + +public class ContinuationEntry extends VMObject { + private static long size; + private static Address returnPC; + + static { + VM.registerVMInitializedObserver((o, d) -> initialize(VM.getVM().getTypeDataBase())); + } + + private static synchronized void initialize(TypeDataBase db) throws WrongTypeException { + Type type = db.lookupType("ContinuationEntry"); + size = type.getSize(); + returnPC = type.getAddressField("_return_pc").getValue(); + } + + public ContinuationEntry(Address addr) { + super(addr); + } + + public Address getEntryPC() { + return returnPC; + } + + public Address getEntrySP(){ + return this.getAddress(); + } + + public Address getEntryFP(){ + return this.getAddress().addOffsetTo(size); + } + +} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java index d92f464f0d2..826b5cecfd5 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/JavaThread.java @@ -47,6 +47,7 @@ public class JavaThread extends Thread { private static AddressField stackBaseField; private static CIntegerField stackSizeField; private static CIntegerField terminatedField; + private static AddressField contEntryField; private static AddressField activeHandlesField; private static CIntegerField monitorOwnerIDField; private static long oopPtrSize; @@ -95,6 +96,7 @@ public class JavaThread extends Thread { stackBaseField = type.getAddressField("_stack_base"); stackSizeField = type.getCIntegerField("_stack_size"); terminatedField = type.getCIntegerField("_terminated"); + contEntryField = type.getAddressField("_cont_entry"); activeHandlesField = type.getAddressField("_active_handles"); monitorOwnerIDField = type.getCIntegerField("_monitor_owner_id"); @@ -340,6 +342,10 @@ public class JavaThread extends Thread { return (int) terminatedField.getValue(addr); } + public ContinuationEntry getContEntry() { + return VMObjectFactory.newObject(ContinuationEntry.class, contEntryField.getValue(addr)); + } + /** Gets the Java-side thread object for this JavaThread */ public Oop getThreadObj() { Oop obj = null; diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/aarch64/AARCH64Frame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/aarch64/AARCH64Frame.java index a5aa7ce4405..5ae4cb703b3 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/aarch64/AARCH64Frame.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/aarch64/AARCH64Frame.java @@ -270,7 +270,13 @@ public class AARCH64Frame extends Frame { } if (cb != null) { - return cb.isUpcallStub() ? senderForUpcallStub(map, (UpcallStub)cb) : senderForCompiledFrame(map, cb); + if (cb.isUpcallStub()) { + return senderForUpcallStub(map, (UpcallStub)cb); + } else if (cb.isContinuationStub()) { + return senderForContinuationStub(map, cb); + } else { + return senderForCompiledFrame(map, cb); + } } // Must be native-compiled frame, i.e. the marshaling code for native @@ -356,6 +362,16 @@ public class AARCH64Frame extends Frame { map.setLocation(fp, savedFPAddr); } + private Frame senderForContinuationStub(AARCH64RegisterMap map, CodeBlob cb) { + var contEntry = map.getThread().getContEntry(); + + Address senderSP = contEntry.getEntrySP(); + Address senderPC = contEntry.getEntryPC(); + Address senderFP = contEntry.getEntryFP(); + + return new AARCH64Frame(senderSP, senderFP, senderPC); + } + private Frame senderForCompiledFrame(AARCH64RegisterMap map, CodeBlob cb) { if (DEBUG) { System.out.println("senderForCompiledFrame"); diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64Frame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64Frame.java index e02e056f028..44c8f4c679c 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64Frame.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/riscv64/RISCV64Frame.java @@ -262,7 +262,13 @@ public class RISCV64Frame extends Frame { } if (cb != null) { - return cb.isUpcallStub() ? senderForUpcallStub(map, (UpcallStub)cb) : senderForCompiledFrame(map, cb); + if (cb.isUpcallStub()) { + return senderForUpcallStub(map, (UpcallStub)cb); + } else if (cb.isContinuationStub()) { + return senderForContinuationStub(map, cb); + } else { + return senderForCompiledFrame(map, cb); + } } // Must be native-compiled frame, i.e. the marshaling code for native @@ -348,6 +354,16 @@ public class RISCV64Frame extends Frame { map.setLocation(fp, savedFPAddr); } + private Frame senderForContinuationStub(RISCV64RegisterMap map, CodeBlob cb) { + var contEntry = map.getThread().getContEntry(); + + Address senderSP = contEntry.getEntrySP(); + Address senderPC = contEntry.getEntryPC(); + Address senderFP = contEntry.getEntryFP(); + + return new RISCV64Frame(senderSP, senderFP, senderPC); + } + private Frame senderForCompiledFrame(RISCV64RegisterMap map, CodeBlob cb) { if (DEBUG) { System.out.println("senderForCompiledFrame"); diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java index 3ee4f0a8158..2d972d3df17 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/x86/X86Frame.java @@ -270,7 +270,13 @@ public class X86Frame extends Frame { } if (cb != null) { - return cb.isUpcallStub() ? senderForUpcallStub(map, (UpcallStub)cb) : senderForCompiledFrame(map, cb); + if (cb.isUpcallStub()) { + return senderForUpcallStub(map, (UpcallStub)cb); + } else if (cb.isContinuationStub()) { + return senderForContinuationStub(map, cb); + } else { + return senderForCompiledFrame(map, cb); + } } // Must be native-compiled frame, i.e. the marshaling code for native @@ -356,6 +362,16 @@ public class X86Frame extends Frame { map.setLocation(rbp, savedFPAddr); } + private Frame senderForContinuationStub(X86RegisterMap map, CodeBlob cb) { + var contEntry = map.getThread().getContEntry(); + + Address senderSP = contEntry.getEntrySP(); + Address senderPC = contEntry.getEntryPC(); + Address senderFP = contEntry.getEntryFP(); + + return new X86Frame(senderSP, senderFP, senderPC); + } + private Frame senderForCompiledFrame(X86RegisterMap map, CodeBlob cb) { if (DEBUG) { System.out.println("senderForCompiledFrame"); diff --git a/test/hotspot/jtreg/serviceability/sa/LingeredAppWithVirtualThread.java b/test/hotspot/jtreg/serviceability/sa/LingeredAppWithVirtualThread.java new file mode 100644 index 00000000000..ca98506e133 --- /dev/null +++ b/test/hotspot/jtreg/serviceability/sa/LingeredAppWithVirtualThread.java @@ -0,0 +1,87 @@ + +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, NTT DATA + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.lang.invoke.MethodHandle; +import java.lang.foreign.Arena; +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.Linker; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.SymbolLookup; +import java.lang.foreign.ValueLayout; +import java.util.concurrent.CountDownLatch; + +import jdk.test.lib.apps.LingeredApp; + +public class LingeredAppWithVirtualThread extends LingeredApp implements Runnable { + + private static final String THREAD_NAME = "target thread"; + + private static final MethodHandle hndSleep; + + private static final int sleepArg; + + private static final CountDownLatch signal = new CountDownLatch(1); + + static { + MemorySegment func; + if (System.getProperty("os.name").startsWith("Windows")) { + func = SymbolLookup.libraryLookup("Kernel32", Arena.global()) + .findOrThrow("Sleep"); + sleepArg = 3600_000; // 1h in milliseconds + } else { + func = Linker.nativeLinker() + .defaultLookup() + .findOrThrow("sleep"); + sleepArg = 3600; // 1h in seconds + } + + var desc = FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.JAVA_INT); + hndSleep = Linker.nativeLinker().downcallHandle(func, desc); + } + + @Override + public void run() { + Thread.yield(); + signal.countDown(); + try { + hndSleep.invoke(sleepArg); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + + public static void main(String[] args) { + try { + Thread.ofVirtual() + .name(THREAD_NAME) + .start(new LingeredAppWithVirtualThread()); + + signal.await(); + LingeredApp.main(args); + } catch (Exception e) { + throw new RuntimeException(e); + } + } +} diff --git a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackWithVirtualThread.java b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackWithVirtualThread.java new file mode 100644 index 00000000000..fce9906ca94 --- /dev/null +++ b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackWithVirtualThread.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, NTT DATA + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import jdk.test.lib.JDKToolLauncher; +import jdk.test.lib.SA.SATestUtils; +import jdk.test.lib.Utils; +import jdk.test.lib.apps.LingeredApp; +import jdk.test.lib.process.OutputAnalyzer; + +/** + * @test + * @bug 8369505 + * @requires vm.hasSA + * @requires (os.arch == "amd64" | os.arch == "x86_64" | os.arch == "aarch64" | os.arch == "riscv64") + * @library /test/lib + * @run driver TestJhsdbJstackWithVirtualThread + */ +public class TestJhsdbJstackWithVirtualThread { + + private static void runJstack(LingeredApp app) throws Exception { + JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jhsdb"); + launcher.addVMArgs(Utils.getTestJavaOpts()); + launcher.addToolArg("jstack"); + launcher.addToolArg("--pid"); + launcher.addToolArg(Long.toString(app.getPid())); + + ProcessBuilder pb = SATestUtils.createProcessBuilder(launcher); + Process jhsdb = pb.start(); + OutputAnalyzer out = new OutputAnalyzer(jhsdb); + + jhsdb.waitFor(); + + System.out.println(out.getStdout()); + System.err.println(out.getStderr()); + + out.stderrShouldBeEmptyIgnoreDeprecatedWarnings(); + out.shouldNotContain("must have non-zero frame size"); + } + + public static void main(String... args) throws Exception { + SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work. + LingeredApp app = null; + + try { + app = new LingeredAppWithVirtualThread(); + LingeredApp.startApp(app); + System.out.println("Started LingeredApp with pid " + app.getPid()); + runJstack(app); + System.out.println("Test Completed"); + } catch (Throwable e) { + e.printStackTrace(); + throw e; + } finally { + LingeredApp.stopApp(app); + } + } +} From f475eb8ee7c9a3e360b2f1210ed71b629243cd2a Mon Sep 17 00:00:00 2001 From: Hamlin Li Date: Thu, 16 Oct 2025 14:04:45 +0000 Subject: [PATCH 0236/1639] 8368950: RISC-V: fail to catch out of order declarations among dependent cpu extensions/flags Reviewed-by: fyang, luhenry --- src/hotspot/cpu/riscv/vm_version_riscv.hpp | 100 +++++++++++------- .../os_cpu/linux_riscv/riscv_hwprobe.cpp | 87 +++++++-------- 2 files changed, 108 insertions(+), 79 deletions(-) diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.hpp b/src/hotspot/cpu/riscv/vm_version_riscv.hpp index 346ca35dc1e..3d555d47e9f 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.hpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.hpp @@ -64,41 +64,12 @@ class VM_Version : public Abstract_VM_Version { virtual void disable_feature() { _value = -1; } - const char* pretty() { return _pretty; } - uint64_t feature_bit() { return _linux_feature_bit; } - bool feature_string() { return _feature_string; } - int64_t value() { return _value; } + const char* pretty() { return _pretty; } + uint64_t feature_bit() { return _linux_feature_bit; } + bool feature_string() { return _feature_string; } + int64_t value() { return _value; } virtual bool enabled() = 0; virtual void update_flag() = 0; - - protected: - bool deps_all_enabled(RVFeatureValue* dep0, ...) { - assert(dep0 != nullptr, "must not"); - - va_list va; - va_start(va, dep0); - RVFeatureValue* next = dep0; - bool enabled = true; - while (next != nullptr && enabled) { - enabled = next->enabled(); - next = va_arg(va, RVFeatureValue*); - } - va_end(va); - return enabled; - } - - void deps_string(stringStream& ss, RVFeatureValue* dep0, ...) { - assert(dep0 != nullptr, "must not"); - ss.print("%s (%s)", dep0->pretty(), dep0->enabled() ? "enabled" : "disabled"); - - va_list va; - va_start(va, dep0); - RVFeatureValue* next = nullptr; - while ((next = va_arg(va, RVFeatureValue*)) != nullptr) { - ss.print(", %s (%s)", next->pretty(), next->enabled() ? "enabled" : "disabled"); - } - va_end(va); - } }; #define UPDATE_DEFAULT(flag) \ @@ -117,8 +88,9 @@ class VM_Version : public Abstract_VM_Version { #define UPDATE_DEFAULT_DEP(flag, dep0, ...) \ void update_flag() { \ assert(enabled(), "Must be."); \ + DEBUG_ONLY(verify_deps(dep0, ##__VA_ARGS__)); \ if (FLAG_IS_DEFAULT(flag)) { \ - if (this->deps_all_enabled(dep0, ##__VA_ARGS__)) { \ + if (deps_all_enabled(dep0, ##__VA_ARGS__)) { \ FLAG_SET_DEFAULT(flag, true); \ } else { \ FLAG_SET_DEFAULT(flag, false); \ @@ -149,11 +121,16 @@ class VM_Version : public Abstract_VM_Version { class RVExtFeatureValue : public RVFeatureValue { const uint32_t _cpu_feature_index; + public: RVExtFeatureValue(const char* pretty, int linux_bit_num, uint32_t cpu_feature_index, bool fstring) : RVFeatureValue(pretty, linux_bit_num, fstring), _cpu_feature_index(cpu_feature_index) { } + int cpu_feature_index() { + // Can be used to check, for example, v is declared before Zvfh in RV_EXT_FEATURE_FLAGS. + return _cpu_feature_index; + } bool enabled() { return RVExtFeatures::current()->support_feature(_cpu_feature_index); } @@ -165,6 +142,57 @@ class VM_Version : public Abstract_VM_Version { RVFeatureValue::disable_feature(); RVExtFeatures::current()->clear_feature(_cpu_feature_index); } + + protected: + bool deps_all_enabled(RVExtFeatureValue* dep0, ...) { + assert(dep0 != nullptr, "must not"); + + va_list va; + va_start(va, dep0); + RVExtFeatureValue* next = dep0; + bool enabled = true; + while (next != nullptr && enabled) { + enabled = next->enabled(); + next = va_arg(va, RVExtFeatureValue*); + } + va_end(va); + return enabled; + } + + void deps_string(stringStream& ss, RVExtFeatureValue* dep0, ...) { + assert(dep0 != nullptr, "must not"); + ss.print("%s (%s)", dep0->pretty(), dep0->enabled() ? "enabled" : "disabled"); + + va_list va; + va_start(va, dep0); + RVExtFeatureValue* next = nullptr; + while ((next = va_arg(va, RVExtFeatureValue*)) != nullptr) { + ss.print(", %s (%s)", next->pretty(), next->enabled() ? "enabled" : "disabled"); + } + va_end(va); + } + +#ifdef ASSERT + void verify_deps(RVExtFeatureValue* dep0, ...) { + assert(dep0 != nullptr, "must not"); + assert(cpu_feature_index() >= 0, "must"); + + va_list va; + va_start(va, dep0); + RVExtFeatureValue* next = dep0; + while (next != nullptr) { + assert(next->cpu_feature_index() >= 0, "must"); + // We only need to check depenency relationship for extension flags. + // The dependant ones must be declared before this, for example, v must be declared + // before Zvfh in RV_EXT_FEATURE_FLAGS. The reason is in setup_cpu_available_features + // we need to make sure v is `update_flag`ed before Zvfh, so Zvfh is `update_flag`ed + // based on v. + assert(cpu_feature_index() > next->cpu_feature_index(), "Invalid"); + next = va_arg(va, RVExtFeatureValue*); + } + va_end(va); + } +#endif // ASSERT }; class RVNonExtFeatureValue : public RVFeatureValue { @@ -282,14 +310,14 @@ class VM_Version : public Abstract_VM_Version { decl(marchid , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ /* A unique encoding of the version of the processor implementation. */ \ decl(mimpid , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ + /* Manufactory JEDEC id encoded, ISA vol 2 3.1.2.. */ \ + decl(mvendorid , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ /* SATP bits (number of virtual addr bits) mbare, sv39, sv48, sv57, sv64 */ \ decl(satp_mode , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ /* Performance of misaligned scalar accesses (unknown, emulated, slow, fast, unsupported) */ \ decl(unaligned_scalar , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ /* Performance of misaligned vector accesses (unknown, unspported, slow, fast) */ \ decl(unaligned_vector , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ - /* Manufactory JEDEC id encoded, ISA vol 2 3.1.2.. */ \ - decl(mvendorid , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ decl(zicboz_block_size , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \ #define DECLARE_RV_NON_EXT_FEATURE(PRETTY, LINUX_BIT, FSTRING, FLAGF) \ diff --git a/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp b/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp index 017d8a43666..ec756c44fe6 100644 --- a/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp +++ b/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp @@ -167,27 +167,20 @@ static bool is_set(int64_t key, uint64_t value_mask) { void RiscvHwprobe::add_features_from_query_result() { assert(rw_hwprobe_completed, "hwprobe not init yet."); - if (is_valid(RISCV_HWPROBE_KEY_MVENDORID)) { - VM_Version::mvendorid.enable_feature(query[RISCV_HWPROBE_KEY_MVENDORID].value); - } - if (is_valid(RISCV_HWPROBE_KEY_MARCHID)) { - VM_Version::marchid.enable_feature(query[RISCV_HWPROBE_KEY_MARCHID].value); - } - if (is_valid(RISCV_HWPROBE_KEY_MIMPID)) { - VM_Version::mimpid.enable_feature(query[RISCV_HWPROBE_KEY_MIMPID].value); - } + // ====== extensions ====== + // if (is_set(RISCV_HWPROBE_KEY_BASE_BEHAVIOR, RISCV_HWPROBE_BASE_BEHAVIOR_IMA)) { + VM_Version::ext_a.enable_feature(); VM_Version::ext_i.enable_feature(); VM_Version::ext_m.enable_feature(); - VM_Version::ext_a.enable_feature(); - } - if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_IMA_FD)) { - VM_Version::ext_f.enable_feature(); - VM_Version::ext_d.enable_feature(); } if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_IMA_C)) { VM_Version::ext_c.enable_feature(); } + if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_IMA_FD)) { + VM_Version::ext_d.enable_feature(); + VM_Version::ext_f.enable_feature(); + } if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_IMA_V)) { // Linux signal return bug when using vector with vlen > 128b in pre 6.8.5. long major, minor, patch; @@ -202,21 +195,29 @@ void RiscvHwprobe::add_features_from_query_result() { VM_Version::ext_v.enable_feature(); } } + +#ifndef PRODUCT + if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZACAS)) { + VM_Version::ext_Zacas.enable_feature(); + } +#endif if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZBA)) { VM_Version::ext_Zba.enable_feature(); } if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZBB)) { VM_Version::ext_Zbb.enable_feature(); } +#ifndef PRODUCT + if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZBKB)) { + VM_Version::ext_Zbkb.enable_feature(); + } +#endif if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZBS)) { VM_Version::ext_Zbs.enable_feature(); } #ifndef PRODUCT - if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZICBOZ)) { - VM_Version::ext_Zicboz.enable_feature(); - } - if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZBKB)) { - VM_Version::ext_Zbkb.enable_feature(); + if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZFA)) { + VM_Version::ext_Zfa.enable_feature(); } #endif if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZFH)) { @@ -226,15 +227,28 @@ void RiscvHwprobe::add_features_from_query_result() { VM_Version::ext_Zfhmin.enable_feature(); } #ifndef PRODUCT + if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZICBOZ)) { + VM_Version::ext_Zicboz.enable_feature(); + } + // Currently tests shows that cmove using Zicond instructions will bring + // performance regression, but to get a test coverage all the time, will + // still prefer to enabling it in debug version. + if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZICOND)) { + VM_Version::ext_Zicond.enable_feature(); + } + if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZTSO)) { + VM_Version::ext_Ztso.enable_feature(); + } if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZVBB)) { VM_Version::ext_Zvbb.enable_feature(); } -#endif -#ifndef PRODUCT if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZVBC)) { VM_Version::ext_Zvbc.enable_feature(); } #endif + if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZVFH)) { + VM_Version::ext_Zvfh.enable_feature(); + } #ifndef PRODUCT if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZVKNED) && is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZVKNHB) && @@ -243,30 +257,18 @@ void RiscvHwprobe::add_features_from_query_result() { VM_Version::ext_Zvkn.enable_feature(); } #endif - if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZVFH)) { - VM_Version::ext_Zvfh.enable_feature(); + + // ====== non-extensions ====== + // + if (is_valid(RISCV_HWPROBE_KEY_MARCHID)) { + VM_Version::marchid.enable_feature(query[RISCV_HWPROBE_KEY_MARCHID].value); } -#ifndef PRODUCT - if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZFA)) { - VM_Version::ext_Zfa.enable_feature(); + if (is_valid(RISCV_HWPROBE_KEY_MIMPID)) { + VM_Version::mimpid.enable_feature(query[RISCV_HWPROBE_KEY_MIMPID].value); } -#endif -#ifndef PRODUCT - if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZTSO)) { - VM_Version::ext_Ztso.enable_feature(); + if (is_valid(RISCV_HWPROBE_KEY_MVENDORID)) { + VM_Version::mvendorid.enable_feature(query[RISCV_HWPROBE_KEY_MVENDORID].value); } -#endif -#ifndef PRODUCT - if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZACAS)) { - VM_Version::ext_Zacas.enable_feature(); - } - // Currently tests shows that cmove using Zicond instructions will bring - // performance regression, but to get a test coverage all the time, will - // still prefer to enabling it in debug version. - if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZICOND)) { - VM_Version::ext_Zicond.enable_feature(); - } -#endif // RISCV_HWPROBE_KEY_CPUPERF_0 is deprecated and returns similar values // to RISCV_HWPROBE_KEY_MISALIGNED_SCALAR_PERF. Keep it there for backward // compatibility with old kernels. @@ -277,7 +279,6 @@ void RiscvHwprobe::add_features_from_query_result() { VM_Version::unaligned_scalar.enable_feature( query[RISCV_HWPROBE_KEY_MISALIGNED_SCALAR_PERF].value); } - if (is_valid(RISCV_HWPROBE_KEY_MISALIGNED_VECTOR_PERF)) { VM_Version::unaligned_vector.enable_feature( query[RISCV_HWPROBE_KEY_MISALIGNED_VECTOR_PERF].value); From 5dfe115ce1fbcff67777518a3c23a7560ebec423 Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Thu, 16 Oct 2025 14:10:14 +0000 Subject: [PATCH 0237/1639] 8369912: [TESTBUG] testlibrary_tests/template_framework/examples/TestExpressions.java fails with ArithmeticException: / by zero - forgot to respect Expression.info Reviewed-by: kvn, mhaessig --- .../examples/TestExpressions.java | 37 +++++++++++++++---- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestExpressions.java b/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestExpressions.java index 6e11a705054..c21d2492fc7 100644 --- a/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestExpressions.java +++ b/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestExpressions.java @@ -70,29 +70,52 @@ public class TestExpressions { var withConstantsTemplate = Template.make("expression", (Expression expression) -> { // Create a token: fill the expression with a fixed set of constants. // We then use the same token with the same constants, once compiled and once not compiled. + // + // Some expressions can throw Exceptions. We have to catch them. In such a case, we return + // the Exception instead of the value from the expression, and compare the Exceptions. + // + // Some Expressions do not have a deterministic result. For example, different NaN or + // precision results from some operators. We only compare the results if we know that the + // result is deterministically the same. TemplateToken expressionToken = expression.asToken(expression.argumentTypes.stream().map(t -> t.con()).toList()); return body( let("returnType", expression.returnType), """ @Test public static void $primitiveConTest() { - #returnType v0 = ${primitiveConTest}_compiled(); - #returnType v1 = ${primitiveConTest}_reference(); - Verify.checkEQ(v0, v1); + Object v0 = ${primitiveConTest}_compiled(); + Object v1 = ${primitiveConTest}_reference(); + """, + expression.info.isResultDeterministic ? "Verify.checkEQ(v0, v1);\n" : "", + """ } @DontInline - public static #returnType ${primitiveConTest}_compiled() { + public static Object ${primitiveConTest}_compiled() { + try { """, - "return ", expressionToken, ";\n", + "return ", expressionToken, ";\n", + expression.info.exceptions.stream().map(exception -> + "} catch (" + exception + " e) { return e;\n" + ).toList(), """ + } finally { + // Just so that javac is happy if there are no exceptions to catch. + } } @DontCompile - public static #returnType ${primitiveConTest}_reference() { + public static Object ${primitiveConTest}_reference() { + try { """, - "return ", expressionToken, ";\n", + "return ", expressionToken, ";\n", + expression.info.exceptions.stream().map(exception -> + "} catch (" + exception + " e) { return e;\n" + ).toList(), """ + } finally { + // Just so that javac is happy if there are no exceptions to catch. + } } """ ); From f2a998326a6bebd4a7d2d0a39f785b2e6dac68c4 Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Thu, 16 Oct 2025 14:22:15 +0000 Subject: [PATCH 0238/1639] 8369804: TestGenerators.java fails with IllegalArgumentException: bound must be greater than origin Reviewed-by: chagedorn, thartmann --- .../generators/UniformDoubleGenerator.java | 3 +++ .../lib/generators/UniformFloatGenerator.java | 3 +++ .../generators/tests/TestGenerators.java | 22 ++++++++++++++----- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/test/hotspot/jtreg/compiler/lib/generators/UniformDoubleGenerator.java b/test/hotspot/jtreg/compiler/lib/generators/UniformDoubleGenerator.java index d160bf319d8..b5729aeec7d 100644 --- a/test/hotspot/jtreg/compiler/lib/generators/UniformDoubleGenerator.java +++ b/test/hotspot/jtreg/compiler/lib/generators/UniformDoubleGenerator.java @@ -35,6 +35,9 @@ final class UniformDoubleGenerator extends UniformIntersectionRestrictableGenera */ public UniformDoubleGenerator(Generators g, double lo, double hi) { super(g, lo, hi); + if (Double.compare(lo, hi) >= 0) { + throw new EmptyGeneratorException(); + } } @Override diff --git a/test/hotspot/jtreg/compiler/lib/generators/UniformFloatGenerator.java b/test/hotspot/jtreg/compiler/lib/generators/UniformFloatGenerator.java index 1b72ad5adc9..4405b120619 100644 --- a/test/hotspot/jtreg/compiler/lib/generators/UniformFloatGenerator.java +++ b/test/hotspot/jtreg/compiler/lib/generators/UniformFloatGenerator.java @@ -35,6 +35,9 @@ final class UniformFloatGenerator extends UniformIntersectionRestrictableGenerat */ public UniformFloatGenerator(Generators g, float lo, float hi) { super(g, lo, hi); + if (Float.compare(lo, hi) >= 0) { + throw new EmptyGeneratorException(); + } } @Override diff --git a/test/hotspot/jtreg/testlibrary_tests/generators/tests/TestGenerators.java b/test/hotspot/jtreg/testlibrary_tests/generators/tests/TestGenerators.java index 8ad0c17ba98..f949f99c035 100644 --- a/test/hotspot/jtreg/testlibrary_tests/generators/tests/TestGenerators.java +++ b/test/hotspot/jtreg/testlibrary_tests/generators/tests/TestGenerators.java @@ -391,13 +391,13 @@ public class TestGenerators { Asserts.assertThrows(EmptyGeneratorException.class, () -> G.uniformDoubles(1, 0)); Asserts.assertNotNull(G.uniformDoubles(0, 1)); - Asserts.assertNotNull(G.uniformDoubles(0, 0)); + Asserts.assertThrows(EmptyGeneratorException.class, () -> G.uniformDoubles(0, 0)); Asserts.assertThrows(EmptyGeneratorException.class, () -> G.uniformDoubles(0, 1).restricted(1.1d, 2.4d)); Asserts.assertNotNull(G.uniformDoubles(0, 1).restricted(0.9d, 2.4d)); Asserts.assertThrows(EmptyGeneratorException.class, () -> G.uniformFloats(1, 0)); Asserts.assertNotNull(G.uniformFloats(0, 1)); - Asserts.assertNotNull(G.uniformFloats(0, 0)); + Asserts.assertThrows(EmptyGeneratorException.class, () -> G.uniformFloats(0, 0)); Asserts.assertThrows(EmptyGeneratorException.class, () -> G.uniformFloats(0, 1).restricted(1.1f, 2.4f)); Asserts.assertNotNull(G.uniformFloats(0, 1).restricted(0.9f, 2.4f)); @@ -592,8 +592,13 @@ public class TestGenerators { var floatBoundGen = G.uniformFloats(); for (int j = 0; j < 500; j++) { - float a = floatBoundGen.next(), b = floatBoundGen.next(); - float lo = Math.min(a, b), hi = Math.max(a, b); + float lo = 1, hi = 0; + // Failure of a single round is very rare, repeated failure even rarer. + while (lo >= hi) { + float a = floatBoundGen.next(), b = floatBoundGen.next(); + lo = Math.min(a, b); + hi = Math.max(a, b); + } var gb = G.uniformFloats(lo, hi); for (int i = 0; i < 10_000; i++) { float x = gb.next(); @@ -604,8 +609,13 @@ public class TestGenerators { var doubleBoundGen = G.uniformDoubles(); for (int j = 0; j < 500; j++) { - double a = doubleBoundGen.next(), b = doubleBoundGen.next(); - double lo = Math.min(a, b), hi = Math.max(a, b); + double lo = 1, hi = 0; + // Failure of a single round is very rare, repeated failure even rarer. + while (lo >= hi) { + double a = doubleBoundGen.next(), b = doubleBoundGen.next(); + lo = Math.min(a, b); + hi = Math.max(a, b); + } var gb = G.uniformDoubles(lo, hi); for (int i = 0; i < 10_000; i++) { double x = gb.next(); From 303eb1096ccaf06106aa080b9ea0553c0f6912dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Lund=C3=A9n?= Date: Thu, 16 Oct 2025 15:02:32 +0000 Subject: [PATCH 0239/1639] 8369573: Add missing compile commands help documentation for the signature part of method patterns Reviewed-by: rcastanedalo, aseoane, thartmann --- src/hotspot/share/compiler/compilerOracle.cpp | 42 +++++++++++++++---- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/src/hotspot/share/compiler/compilerOracle.cpp b/src/hotspot/share/compiler/compilerOracle.cpp index 868ae8bfa41..23bb754f432 100644 --- a/src/hotspot/share/compiler/compilerOracle.cpp +++ b/src/hotspot/share/compiler/compilerOracle.cpp @@ -617,18 +617,44 @@ static void usage() { tty->cr(); print_commands(); tty->cr(); - tty->print_cr("Method patterns has the format:"); - tty->print_cr(" package/Class.method()"); + tty->print_cr("The has the format '.'."); + tty->cr(); + tty->print_cr("For example, the "); + tty->cr(); + tty->print_cr(" package/Class.method(Lpackage/Parameter;)Lpackage/Return;"); + tty->cr(); + tty->print_cr("matches the 'method' in 'package/Class' with "); + tty->print_cr("'(Lpackage/Parameter;)Lpackage/Return;'"); tty->cr(); tty->print_cr("For backward compatibility this form is also allowed:"); - tty->print_cr(" package.Class::method()"); tty->cr(); - tty->print_cr("The signature can be separated by an optional whitespace or comma:"); - tty->print_cr(" package/Class.method ()"); + tty->print_cr(" package.Class::method(Lpackage.Parameter;)Lpackage.Return;"); tty->cr(); - tty->print_cr("The class and method identifier can be used together with leading or"); - tty->print_cr("trailing *'s for wildcard matching:"); - tty->print_cr(" *ackage/Clas*.*etho*()"); + tty->print_cr("A whitespace or comma can optionally separate the from the"); + tty->print_cr(":"); + tty->cr(); + tty->print_cr(" package/Class.method (Lpackage/Parameter;)Lpackage/Return;"); + tty->print_cr(" package/Class.method,(Lpackage/Parameter;)Lpackage/Return;"); + tty->cr(); + tty->print_cr("The and accept leading and trailing '*' wildcards"); + tty->print_cr("matching:"); + tty->cr(); + tty->print_cr(" *ackage/Clas*.*etho*(Lpackage/Parameter;)Lpackage/Return;"); + tty->cr(); + tty->print_cr("The does not support explicit wildcards and"); + tty->print_cr("always has an implicit trailing wildcard. Therefore,"); + tty->cr(); + tty->print_cr(" package/Class.method(Lpackage/Parameter;)Lpackage/Return;"); + tty->cr(); + tty->print_cr("matches a subset of"); + tty->cr(); + tty->print_cr(" package/Class.method(Lpackage/Parameter;)"); + tty->cr(); + tty->print_cr("which matches a subset of"); + tty->cr(); + tty->print_cr(" package/Class.method"); + tty->cr(); + tty->print_cr("which matches all possible descriptors."); tty->cr(); tty->print_cr("It is possible to use more than one CompileCommand on the command line:"); tty->print_cr(" -XX:CompileCommand=exclude,java/*.* -XX:CompileCommand=log,java*.*"); From 87092ef1d97e00ddb6674b0e309f2f904d307604 Mon Sep 17 00:00:00 2001 From: Arno Zeller Date: Thu, 16 Oct 2025 15:15:19 +0000 Subject: [PATCH 0240/1639] 8183336: Better cleanup for jdk/test/java/lang/module/customfs/ModulesInCustomFileSystem.java Reviewed-by: alanb, syan --- .../java/lang/module/customfs/ModulesInCustomFileSystem.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/jdk/java/lang/module/customfs/ModulesInCustomFileSystem.java b/test/jdk/java/lang/module/customfs/ModulesInCustomFileSystem.java index 801f2e5fca6..e023a3a5839 100644 --- a/test/jdk/java/lang/module/customfs/ModulesInCustomFileSystem.java +++ b/test/jdk/java/lang/module/customfs/ModulesInCustomFileSystem.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,7 @@ * @library /test/lib * @build ModulesInCustomFileSystem m1/* m2/* * jdk.test.lib.util.JarUtils - * @run testng/othervm ModulesInCustomFileSystem + * @run testng/othervm -Djava.io.tmpdir=. ModulesInCustomFileSystem * @summary Test ModuleFinder to find modules in a custom file system */ From 95380e1ea5c3f531f82fb7c4b2f75726f3cd2fc2 Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Thu, 16 Oct 2025 15:54:22 +0000 Subject: [PATCH 0241/1639] 8362637: Convert java.nio.ByteOrder to an enum Reviewed-by: alanb, liach, bpb --- .../share/classes/java/nio/ByteOrder.java | 41 ++++--------------- 1 file changed, 9 insertions(+), 32 deletions(-) diff --git a/src/java.base/share/classes/java/nio/ByteOrder.java b/src/java.base/share/classes/java/nio/ByteOrder.java index 96f2317b956..ab6876448be 100644 --- a/src/java.base/share/classes/java/nio/ByteOrder.java +++ b/src/java.base/share/classes/java/nio/ByteOrder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,28 +35,19 @@ import jdk.internal.misc.Unsafe; * @since 1.4 */ -public final class ByteOrder { - - private final String name; - - private ByteOrder(String name) { - this.name = name; - } - - /** - * Constant denoting big-endian byte order. In this order, the bytes of a - * multibyte value are ordered from most significant to least significant. - */ - public static final ByteOrder BIG_ENDIAN - = new ByteOrder("BIG_ENDIAN"); - +public enum ByteOrder { /** * Constant denoting little-endian byte order. In this order, the bytes of * a multibyte value are ordered from least significant to most * significant. */ - public static final ByteOrder LITTLE_ENDIAN - = new ByteOrder("LITTLE_ENDIAN"); + LITTLE_ENDIAN, + /** + * Constant denoting big-endian byte order. In this order, the bytes of a + * multibyte value are ordered from most significant to least significant. + */ + BIG_ENDIAN; + // Retrieve the native byte order. It's used early during bootstrap, and // must be initialized after BIG_ENDIAN and LITTLE_ENDIAN. @@ -78,18 +69,4 @@ public final class ByteOrder { public static ByteOrder nativeOrder() { return NATIVE_ORDER; } - - /** - * Constructs a string describing this object. - * - *

    This method returns the string - * {@code "BIG_ENDIAN"} for {@link #BIG_ENDIAN} and - * {@code "LITTLE_ENDIAN"} for {@link #LITTLE_ENDIAN}. - * - * @return The specified string - */ - public String toString() { - return name; - } - } From e56db37734aa7cbc0f20ba3fc469f51224f288fa Mon Sep 17 00:00:00 2001 From: Christian Hagedorn Date: Thu, 16 Oct 2025 16:02:26 +0000 Subject: [PATCH 0242/1639] 8369232: testlibrary_tests/ir_framework/tests/TestScenariosCrossProduct.java timed out Reviewed-by: dfenacci, epeter --- .../lib/ir_framework/TestFramework.java | 27 +- .../tests/TestScenariosCrossProduct.java | 384 +++++++++++++----- 2 files changed, 305 insertions(+), 106 deletions(-) diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java index 85c52ef33da..09e291ce5a4 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java @@ -327,8 +327,10 @@ public class TestFramework { for (Scenario scenario : scenarios) { int scenarioIndex = scenario.getIndex(); - TestFormat.checkNoThrow(scenarioIndices.add(scenarioIndex), - "Cannot define two scenarios with the same index " + scenarioIndex); + if (!scenarioIndices.add(scenarioIndex)) { + TestFormat.failNoThrow("Cannot define two scenarios with the same index " + scenarioIndex); + continue; + } this.scenarios.add(scenario); } TestFormat.throwIfAnyFailures(); @@ -336,9 +338,12 @@ public class TestFramework { } /** - * Add the cross-product (cartesian product) of sets of flags as Scenarios. Unlike when when constructing + * Add the cross-product (cartesian product) of sets of flags as Scenarios. Unlike when constructing * scenarios directly a string can contain multiple flags separated with a space. This allows grouping - * flags that have to be specified togeher. Further, an empty string in a set stands in for "no flag". + * flags that have to be specified together. Further, an empty string in a set stands in for "no flag". + *

    + * Passing a single set will create a scenario for each of the provided flags in the set (i.e. the same as + * passing an additional set with an empty string only). *

    * Example: *

    @@ -355,7 +360,7 @@ public class TestFramework {
          *     Scenario(5, "-Xbatch -XX:-TieredCompilation", "-XX:+UseNewCode2")
          * 
    * - * @param sets sets of flags to generate the cross product for. + * @param flagSets sets of flags to generate the cross product for. * @return the same framework instance. */ @SafeVarargs @@ -376,7 +381,7 @@ public class TestFramework { Stream> crossProduct = Arrays.stream(flagSets) .reduce( - Stream.of(Collections.emptyList()), // Initialize Stream> acc with a Stream containing an empty list of Strings. + Stream.of(Collections.emptyList()), // Initialize Stream> acc with a Stream containing an empty list of Strings. (Stream> acc, Set set) -> acc.flatMap(lAcc -> // For each List> lAcc in acc... set.stream().map(flag -> { // ...and each flag in the current set... @@ -384,19 +389,19 @@ public class TestFramework { newList.add(flag); // ...and append the flag. return newList; }) // This results in one List> for each lAcc... - ), // ...that get flattend into one big List>. - (a, b) -> Stream.concat(a, b)); // combiner; if any reduction steps are executed in parallel, just concat two streams. + ), // ...that get flattened into one big List>. + Stream::concat); // combiner; if any reduction steps are executed in parallel, just concat two streams. Scenario[] newScenarios = crossProduct .map(flags -> new Scenario( // For each List flags in crossProduct create a new Scenario. idx.getAndIncrement(), flags.stream() // Process flags - .map(s -> Set.of(s.split("[ ]"))) // Split muliple flags in the same string into separate strings. + .map(s -> Set.of(s.split("[ ]"))) // Split multiple flags in the same string into separate strings. .flatMap(Collection::stream) // Flatten the Stream> into Stream>. .filter(s -> !s.isEmpty()) // Remove empty string flags. - .collect(Collectors.toList()) + .toList() .toArray(new String[0]))) - .collect(Collectors.toList()).toArray(new Scenario[0]); + .toList().toArray(new Scenario[0]); return addScenarios(newScenarios); } diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestScenariosCrossProduct.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestScenariosCrossProduct.java index 496fcbddb0f..46813bbff78 100644 --- a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestScenariosCrossProduct.java +++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestScenariosCrossProduct.java @@ -23,15 +23,22 @@ package ir_framework.tests; -import java.util.Set; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.lang.reflect.Field; +import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; import compiler.lib.ir_framework.*; -import compiler.lib.ir_framework.shared.TestRunException; import compiler.lib.ir_framework.shared.TestFormatException; +import compiler.lib.ir_framework.shared.TestRunException; import jdk.test.lib.Asserts; /* * @test + * @bug 8365262 8369232 * @requires vm.debug == true & vm.compMode != "Xint" & vm.compiler2.enabled & vm.flagless * @summary Test cross product scenarios with the framework. * @library /test/lib /testlibrary_tests / @@ -39,29 +46,20 @@ import jdk.test.lib.Asserts; */ public class TestScenariosCrossProduct { - static void hasNFailures(String s, int count) { - if (!s.matches("The following scenarios have failed: (#[0-9](, )?){" + count + "}. Please check stderr for more information.")) { - throw new RuntimeException("Expected " + count + " failures in \"" + s + "\""); - } - } public static void main(String[] args) { - // Test argument handling - try { - TestFramework t = new TestFramework(); - t.addCrossProductScenarios((Set[]) null); - Asserts.fail("Should have thrown exception"); - } catch (TestFormatException e) {} - try { - TestFramework t = new TestFramework(); - t.addCrossProductScenarios(Set.of("foo", "bar"), null); - Asserts.fail("Should have thrown exception"); - } catch (TestFormatException e) {} + expectFormatFailure((Set[]) null); + expectFormatFailure(Set.of("foo", "bar"), null); + try { TestFramework t = new TestFramework(); t.addCrossProductScenarios(Set.of("blub"), Set.of("foo", null)); - Asserts.fail("Should have thrown exception"); - } catch (NullPointerException e) {} // Set.of prevents null elements + shouldHaveThrown(); + } catch (NullPointerException _) { + // Expected: Set.of prevents null elements + } + + try { TestFramework t = new TestFramework(); t.addCrossProductScenarios(); @@ -70,95 +68,291 @@ public class TestScenariosCrossProduct { } // Single set should test all flags in the set by themselves. - try { - TestFramework t1 = new TestFramework(); - t1.addCrossProductScenarios(Set.of("-XX:TLABRefillWasteFraction=51", - "-XX:TLABRefillWasteFraction=53", - "-XX:TLABRefillWasteFraction=64")); - t1.start(); - Asserts.fail("Should have thrown exception"); - } catch (TestRunException e) { - hasNFailures(e.getMessage(), 3); - } + new TestCase() + .inputFlags(Set.of( + Set.of("-XX:TLABRefillWasteFraction=51", + "-XX:TLABRefillWasteFraction=53", + "-XX:TLABRefillWasteFraction=64") + ) + ) + .expectedScenariosWithFlags(Set.of( + Set.of("-XX:TLABRefillWasteFraction=51"), + Set.of("-XX:TLABRefillWasteFraction=53"), + Set.of("-XX:TLABRefillWasteFraction=64") + )) + .run(); // The cross product of a set with one element and a set with three elements is three sets. - try { - TestFramework t2 = new TestFramework(); - t2.addCrossProductScenarios(Set.of("-XX:TLABRefillWasteFraction=53"), - Set.of("-XX:+UseNewCode", "-XX:+UseNewCode2", "-XX:+UseNewCode3")); - t2.start(); - Asserts.fail("Should have thrown exception"); - } catch (TestRunException e) { - hasNFailures(e.getMessage(), 3); - } + new TestCase() + .inputFlags(Set.of( + Set.of("-XX:TLABRefillWasteFraction=53"), + Set.of("-XX:+UseNewCode", "-XX:+UseNewCode2", "-XX:+UseNewCode3") + ) + ) + .expectedScenariosWithFlags(Set.of( + Set.of("-XX:TLABRefillWasteFraction=53", "-XX:+UseNewCode"), + Set.of("-XX:TLABRefillWasteFraction=53", "-XX:+UseNewCode2"), + Set.of("-XX:TLABRefillWasteFraction=53", "-XX:+UseNewCode3") + )) + .run(); + // The cross product of two sets with two elements is four sets. - try { - TestFramework t3 = new TestFramework(); - t3.addCrossProductScenarios(Set.of("-XX:TLABRefillWasteFraction=53", "-XX:TLABRefillWasteFraction=64"), - Set.of("-XX:+UseNewCode", "-XX:-UseNewCode")); - t3.start(); - Asserts.fail("Should have thrown exception"); - } catch (TestRunException e) { - hasNFailures(e.getMessage(), 4); - } + new TestCase() + .inputFlags(Set.of( + Set.of("-XX:TLABRefillWasteFraction=53", "-XX:TLABRefillWasteFraction=64"), + Set.of("-XX:+UseNewCode", "-XX:-UseNewCode") + ) + ) + .expectedScenariosWithFlags(Set.of( + Set.of("-XX:TLABRefillWasteFraction=53", "-XX:+UseNewCode"), + Set.of("-XX:TLABRefillWasteFraction=53", "-XX:-UseNewCode"), + Set.of("-XX:TLABRefillWasteFraction=64", "-XX:+UseNewCode"), + Set.of("-XX:TLABRefillWasteFraction=64", "-XX:-UseNewCode") + )) + .run(); + // Test with a pair of flags. - try { - TestFramework t4 = new TestFramework(); - t4.addCrossProductScenarios(Set.of("-XX:TLABRefillWasteFraction=50 -XX:+UseNewCode", "-XX:TLABRefillWasteFraction=40"), - Set.of("-XX:+UseNewCode2")); - t4.start(); - Asserts.fail("Should have thrown exception"); - } catch (TestRunException e) { - hasNFailures(e.getMessage(), 1); - } + new TestCase() + .inputFlags(Set.of( + Set.of("-XX:TLABRefillWasteFraction=50 -XX:+UseNewCode", "-XX:TLABRefillWasteFraction=40"), + Set.of("-XX:+UseNewCode2") + ) + ) + .expectedScenariosWithFlags(Set.of( + Set.of("-XX:TLABRefillWasteFraction=50", "-XX:+UseNewCode", "-XX:+UseNewCode2"), + Set.of("-XX:TLABRefillWasteFraction=40", "-XX:+UseNewCode2") + )) + .run(); - // Test with an empty string. All 6 scenarios fail because 64 is the default value for TLABRefillWasteFraction. - try { - TestFramework t5 = new TestFramework(); - t5.addCrossProductScenarios(Set.of("", "-XX:TLABRefillWasteFraction=51", "-XX:TLABRefillWasteFraction=53"), - Set.of("-XX:+UseNewCode", "-XX:+UseNewCode2")); - t5.start(); - Asserts.fail("Should have thrown exception"); - } catch (TestRunException e) { - hasNFailures(e.getMessage(), 6); - } + // Test with an empty string, resulting in 6 scenarios. + new TestCase() + .inputFlags(Set.of( + Set.of("", "-XX:TLABRefillWasteFraction=51", "-XX:TLABRefillWasteFraction=53"), + Set.of("-XX:+UseNewCode", "-XX:+UseNewCode2") + ) + ) + .expectedScenariosWithFlags(Set.of( + Set.of("-XX:+UseNewCode"), + Set.of("-XX:+UseNewCode2"), + Set.of("-XX:TLABRefillWasteFraction=51", "-XX:+UseNewCode"), + Set.of("-XX:TLABRefillWasteFraction=51", "-XX:+UseNewCode2"), + Set.of("-XX:TLABRefillWasteFraction=53", "-XX:+UseNewCode"), + Set.of("-XX:TLABRefillWasteFraction=53", "-XX:+UseNewCode2") + )) + .run(); + // Test with 3 input sets which equals to 2x2x2 = 8 scenarios. + new TestCase() + .inputFlags(Set.of( + Set.of("-XX:TLABRefillWasteFraction=51", + "-XX:TLABRefillWasteFraction=53"), + Set.of("-XX:+UseNewCode", + "-XX:-UseNewCode"), + Set.of("-XX:+UseNewCode2", + "-XX:-UseNewCode2") + ) + ) + .expectedScenariosWithFlags(Set.of( + Set.of("-XX:TLABRefillWasteFraction=51", "-XX:+UseNewCode", "-XX:+UseNewCode2"), + Set.of("-XX:TLABRefillWasteFraction=53", "-XX:+UseNewCode", "-XX:+UseNewCode2"), + Set.of("-XX:TLABRefillWasteFraction=51", "-XX:-UseNewCode", "-XX:+UseNewCode2"), + Set.of("-XX:TLABRefillWasteFraction=53", "-XX:-UseNewCode", "-XX:+UseNewCode2"), + Set.of("-XX:TLABRefillWasteFraction=51", "-XX:+UseNewCode", "-XX:-UseNewCode2"), + Set.of("-XX:TLABRefillWasteFraction=53", "-XX:+UseNewCode", "-XX:-UseNewCode2"), + Set.of("-XX:TLABRefillWasteFraction=51", "-XX:-UseNewCode", "-XX:-UseNewCode2"), + Set.of("-XX:TLABRefillWasteFraction=53", "-XX:-UseNewCode", "-XX:-UseNewCode2") + )) + .run(); + + TestFramework testFramework = new TestFramework(); + testFramework.addScenarios(new Scenario(0, "-XX:TLABRefillWasteFraction=50", "-XX:+UseNewCode")); + testFramework.addCrossProductScenarios(Set.of("-XX:TLABRefillWasteFraction=51", "-XX:TLABRefillWasteFraction=53"), + Set.of("-XX:+UseNewCode", "-XX:+UseNewCode2")); try { - TestFramework t6 = new TestFramework(); - t6.addScenarios(new Scenario(0, "-XX:TLABRefillWasteFraction=50", "-XX:+UseNewCode")); // failPair - t6.addCrossProductScenarios(Set.of("-XX:TLABRefillWasteFraction=51", "-XX:TLABRefillWasteFraction=53"), - Set.of("-XX:+UseNewCode", "-XX:+UseNewCode2")); - try { - t6.addScenarios(new Scenario(4, "-XX:+UseNewCode3")); // fails because index 4 is already used - Asserts.fail("Should have thrown exception"); - } catch (TestFormatException e) {} - t6.addScenarios(new Scenario(5, "-XX:+UseNewCode3")); // fail default - t6.start(); - Asserts.fail("Should have thrown exception"); - } catch (TestRunException e) { - hasNFailures(e.getMessage(), 6); + testFramework.addScenarios(new Scenario(4, "-XX:+UseNewCode3")); // fails because index 4 is already used + shouldHaveThrown(); + } catch (TestFormatException _) { + // Expected. + } + testFramework.addScenarios(new Scenario(5, "-XX:+UseNewCode3")); + + new TestCase() + .expectedScenariosWithFlags(Set.of( + Set.of("-XX:TLABRefillWasteFraction=50", "-XX:+UseNewCode"), + Set.of("-XX:TLABRefillWasteFraction=51", "-XX:+UseNewCode"), + Set.of("-XX:TLABRefillWasteFraction=51", "-XX:+UseNewCode2"), + Set.of("-XX:TLABRefillWasteFraction=53", "-XX:+UseNewCode"), + Set.of("-XX:TLABRefillWasteFraction=53", "-XX:+UseNewCode2"), + Set.of("-XX:+UseNewCode3") + )) + .runWithPreAddedScenarios(testFramework); + + runEndToEndTest(); + } + + private static void expectFormatFailure(Set... flagSets) { + TestFramework testFramework = new TestFramework(); + try { + testFramework.addCrossProductScenarios(flagSets); + shouldHaveThrown(); + } catch (TestFormatException _) { + // Expected. } } - @Test - @IR(applyIf = {"TLABRefillWasteFraction", "64"}, counts = {IRNode.CALL, "1"}) - public void failDefault() { + private static void shouldHaveThrown() { + Asserts.fail("Should have thrown exception"); + } + + static class TestCase { + private Set> inputFlags; + private Set> expectedScenariosWithFlags; + + public TestCase inputFlags(Set> inputFlags) { + this.inputFlags = inputFlags; + return this; + } + + public TestCase expectedScenariosWithFlags(Set> expectedScenariosWithFlags) { + this.expectedScenariosWithFlags = expectedScenariosWithFlags; + return this; + } + + public void run() { + TestFramework testFramework = new TestFramework(); + testFramework.addCrossProductScenarios(inputFlags.toArray(new Set[0])); + runWithPreAddedScenarios(testFramework); + } + + public void runWithPreAddedScenarios(TestFramework testFramework) { + List scenariosFromCrossProduct = getScenarios(testFramework); + assertScenarioCount(expectedScenariosWithFlags.size(), scenariosFromCrossProduct); + assertScenariosWithFlags(scenariosFromCrossProduct, expectedScenariosWithFlags); + assertSameResultWhenManuallyAdding(scenariosFromCrossProduct, expectedScenariosWithFlags); + } + + private static void assertScenarioCount(int expectedCount, List scenarios) { + Asserts.assertEQ(expectedCount, scenarios.size(), "Scenario count is off"); + } + + /** + * Check that the added scenarios to the IR framework with TestFramework.addCrossProductScenarios() + * (i.e. 'scenariosFromCrossProduct') match the expected flag combos (i.e. 'expectedScenariosWithFlags'). + */ + private static void assertScenariosWithFlags(List scenariosFromCrossProduct, + Set> expectedScenariosWithFlags) { + for (Set expectedScenarioFlags : expectedScenariosWithFlags) { + if (scenariosFromCrossProduct.stream() + .map(Scenario::getFlags) + .map(Set::copyOf) + .anyMatch(flags -> flags.equals(expectedScenarioFlags))) { + continue; + } + System.err.println("Scenarios from cross product:"); + for (Scenario s : scenariosFromCrossProduct) { + System.err.println(Arrays.toString(s.getFlags().toArray())); + } + throw new RuntimeException("Could not find a scenario with the provided flags: " + Arrays.toString(expectedScenarioFlags.toArray())); + } + } + + /** + * Add scenarios for the provided flag sets in 'expectedScenariosWithFlags' by using TestFramework.addScenarios(). + * We should end up with the same scenarios as if we added them with TestFramework.addCrossProductScenarios(). + * This is verified by this method by comparing the flags of the scenarios, ignoring scenario indices. + */ + private static void assertSameResultWhenManuallyAdding(List scenariosFromCrossProduct, + Set> expectedScenariosWithFlags) { + List expectedScenarios = getScenariosWithFlags(expectedScenariosWithFlags); + List fetchedScenarios = addScenariosAndFetchFromFramework(expectedScenarios); + assertSameScenarios(scenariosFromCrossProduct, fetchedScenarios); + } + + private static List getScenariosWithFlags(Set> expectedScenariosWithFlags) { + List expecedScenarioList = new ArrayList<>(); + int index = -1; // Use some different indices - should not matter what we choose. + for (Set expectedScenarioFlags : expectedScenariosWithFlags) { + expecedScenarioList.add(new Scenario(index--, expectedScenarioFlags.toArray(new String[0]))); + } + return expecedScenarioList; + } + + private static List addScenariosAndFetchFromFramework(List expecedScenarioList) { + TestFramework testFramework = new TestFramework(); + testFramework.addScenarios(expecedScenarioList.toArray(new Scenario[0])); + return getScenarios(testFramework); + } + + private static void assertSameScenarios(List scenariosFromCrossProduct, + List expectedScenarios) { + assertScenariosWithFlags(scenariosFromCrossProduct, fetchFlags(expectedScenarios)); + } + + private static Set> fetchFlags(List scenarios) { + return scenarios.stream() + .map(scenario -> new HashSet<>(scenario.getFlags())) + .collect(Collectors.toSet()); + } + } + + private static List getScenarios(TestFramework testFramework) { + Field field; + try { + field = TestFramework.class.getDeclaredField("scenarios"); + field.setAccessible(true); + return (List)field.get(testFramework); + } catch (NoSuchFieldException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + /** + * Also run a simple end-to-end test to sanity check the API method. We capture the stderr to fetch the + * scenario flags. + */ + private static void runEndToEndTest() { + TestFramework testFramework = new TestFramework(); + + // Capture stderr + PrintStream originalErr = System.err; + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + PrintStream printStream = new PrintStream(outputStream); + System.setErr(printStream); + + try { + testFramework + .addCrossProductScenarios(Set.of("-XX:+UseNewCode", "-XX:-UseNewCode"), + Set.of("-XX:+UseNewCode2", "-XX:-UseNewCode2")) + .addFlags() + .start(); + shouldHaveThrown(); + } catch (TestRunException e) { + // Expected. + System.setErr(originalErr); + Asserts.assertTrue(e.getMessage().contains("The following scenarios have failed: #0, #1, #2, #3.")); + String stdErr = outputStream.toString(); + Asserts.assertTrue(stdErr.contains("Scenario flags: [-XX:+UseNewCode, -XX:+UseNewCode2]")); + Asserts.assertTrue(stdErr.contains("Scenario flags: [-XX:-UseNewCode, -XX:-UseNewCode2]")); + Asserts.assertTrue(stdErr.contains("Scenario flags: [-XX:+UseNewCode, -XX:-UseNewCode2]")); + Asserts.assertTrue(stdErr.contains("Scenario flags: [-XX:-UseNewCode, -XX:+UseNewCode2]")); + Asserts.assertEQ(4, scenarioCount(stdErr)); + } + } + + public static int scenarioCount(String stdErr) { + Pattern pattern = Pattern.compile("Scenario flags"); + Matcher matcher = pattern.matcher(stdErr); + int count = 0; + while (matcher.find()) { + count++; + } + return count; } @Test - @IR(applyIf = {"TLABRefillWasteFraction", "51"}, counts = {IRNode.CALL, "1"}) - public void fail1() { - } - - @Test - @IR(applyIf = {"TLABRefillWasteFraction", "53"}, counts = {IRNode.CALL, "1"}) - public void fail2() { - } - - @Test - @IR(applyIfAnd = {"TLABRefillWasteFraction", "50", "UseNewCode", "true"}, counts = {IRNode.CALL, "1"}) - public void failPair() { + public void endToEndTest() { + throw new RuntimeException("executed test"); } } From 7e03240974cd66c471f5d02e14fd77971fe6d173 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Thu, 16 Oct 2025 16:38:18 +0000 Subject: [PATCH 0243/1639] 8369858: Remove darcy author tags from jdk tests Reviewed-by: rriggs, iris, lancea --- test/jdk/java/io/Serializable/cloneArray/CloneArray.java | 3 +-- test/jdk/java/lang/Byte/Decode.java | 4 +--- test/jdk/java/lang/Class/IsAnnotationType.java | 3 +-- test/jdk/java/lang/Class/IsEnum.java | 3 +-- test/jdk/java/lang/Class/IsSynthetic.java | 3 +-- .../getEnclosingConstructor/EnclosingConstructorTests.java | 3 +-- .../lang/Class/getEnclosingMethod/EnclosingMethodTests.java | 3 +-- test/jdk/java/lang/Double/BitwiseConversion.java | 3 +-- test/jdk/java/lang/Double/Constants.java | 3 +-- test/jdk/java/lang/Double/Extrema.java | 3 +-- test/jdk/java/lang/Double/NaNInfinityParsing.java | 3 +-- test/jdk/java/lang/Double/ParseHexFloatingPoint.java | 3 +-- test/jdk/java/lang/Double/ToHexString.java | 3 +-- test/jdk/java/lang/Float/BitwiseConversion.java | 3 +-- test/jdk/java/lang/Float/Constants.java | 3 +-- test/jdk/java/lang/Float/Extrema.java | 3 +-- test/jdk/java/lang/Float/NaNInfinityParsing.java | 3 +-- test/jdk/java/lang/Integer/Decode.java | 4 +--- test/jdk/java/lang/Integer/ParsingTest.java | 3 +-- test/jdk/java/lang/Integer/Unsigned.java | 3 +-- test/jdk/java/lang/Long/Decode.java | 4 +--- test/jdk/java/lang/Long/ParsingTest.java | 3 +-- test/jdk/java/lang/Long/Unsigned.java | 3 +-- test/jdk/java/lang/Short/Decode.java | 4 +--- test/jdk/java/lang/Throwable/SuppressedExceptions.java | 3 +-- test/jdk/java/lang/annotation/Missing/MissingTest.java | 3 +-- .../lang/annotation/TestIncompleteAnnotationExceptionNPE.java | 3 +-- .../AnnotatedElement/TestAnnotatedElementDefaults.java | 3 +-- test/jdk/java/lang/reflect/Constructor/GenericStringTest.java | 3 +-- .../lang/reflect/Constructor/TestParameterAnnotations.java | 3 +-- test/jdk/java/lang/reflect/DefaultAccessibility.java | 3 +-- test/jdk/java/lang/reflect/Field/GenericStringTest.java | 3 +-- test/jdk/java/lang/reflect/Generics/HashCodeTest.java | 3 +-- test/jdk/java/lang/reflect/Generics/Probe.java | 3 +-- test/jdk/java/lang/reflect/Generics/StringsAndBounds.java | 3 +-- .../jdk/java/lang/reflect/Generics/TestParameterizedType.java | 3 +-- test/jdk/java/lang/reflect/Generics/exceptionCauseTest.java | 3 +-- test/jdk/java/lang/reflect/Generics/getAnnotationTest.java | 3 +-- test/jdk/java/lang/reflect/Method/GenericStringTest.java | 3 +-- test/jdk/java/lang/reflect/Method/IsDefaultTest.java | 3 +-- .../Method/defaultMethodModeling/DefaultMethodModeling.java | 3 +-- .../java/lang/reflect/TypeVariable/TestAnnotatedElement.java | 3 +-- test/jdk/java/math/BigDecimal/AddTests.java | 3 +-- test/jdk/java/math/BigDecimal/CompareToTests.java | 3 +-- test/jdk/java/math/BigDecimal/DivideTests.java | 3 +-- test/jdk/java/math/BigDecimal/IntegralDivisionTests.java | 3 +-- test/jdk/java/math/BigDecimal/NegateTests.java | 3 +-- test/jdk/java/math/BigDecimal/PowTests.java | 3 +-- test/jdk/java/math/BigDecimal/PrecisionTests.java | 3 +-- test/jdk/java/math/BigDecimal/RoundingTests.java | 3 +-- test/jdk/java/math/BigDecimal/ScaleByPowerOfTenTests.java | 3 +-- test/jdk/java/math/BigDecimal/StrippingZerosTest.java | 3 +-- test/jdk/java/math/BigDecimal/ToPlainStringTests.java | 3 +-- test/jdk/java/math/BigDecimal/ZeroScalingTests.java | 3 +-- test/jdk/java/math/BigInteger/CompareToTests.java | 3 +-- test/jdk/java/math/BigInteger/ExtremeShiftingTests.java | 3 +-- test/jdk/java/math/BigInteger/OperatorNpeTests.java | 3 +-- test/jdk/java/math/BigInteger/StringConstructor.java | 3 +-- test/jdk/java/math/BigInteger/TestValueExact.java | 3 +-- test/jdk/java/math/RoundingMode/RoundingModeTests.java | 3 +-- test/jdk/tools/launcher/ChangeDataModel.java | 3 +-- test/jdk/tools/launcher/I18NTest.java | 3 +-- test/jdk/tools/launcher/UnresolvedExceptions.java | 3 +-- 63 files changed, 63 insertions(+), 130 deletions(-) diff --git a/test/jdk/java/io/Serializable/cloneArray/CloneArray.java b/test/jdk/java/io/Serializable/cloneArray/CloneArray.java index a8de4407912..0a427e29da5 100644 --- a/test/jdk/java/io/Serializable/cloneArray/CloneArray.java +++ b/test/jdk/java/io/Serializable/cloneArray/CloneArray.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ /* @test * @bug 6990094 * @summary Verify ObjectInputStream.cloneArray works on many kinds of arrays - * @author Stuart Marks, Joseph D. Darcy */ import java.io.ByteArrayInputStream; diff --git a/test/jdk/java/lang/Byte/Decode.java b/test/jdk/java/lang/Byte/Decode.java index b4ef798cb7e..590c35989f7 100644 --- a/test/jdk/java/lang/Byte/Decode.java +++ b/test/jdk/java/lang/Byte/Decode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,6 @@ * @test * @bug 4242173 5017980 6576055 * @summary Test Byte.decode method - * @author madbot - * @author Joseph D. Darcy */ /** diff --git a/test/jdk/java/lang/Class/IsAnnotationType.java b/test/jdk/java/lang/Class/IsAnnotationType.java index 2189e1c5715..e007201d95c 100644 --- a/test/jdk/java/lang/Class/IsAnnotationType.java +++ b/test/jdk/java/lang/Class/IsAnnotationType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 4891872 4988155 * @summary Check isAnnotation() method - * @author Joseph D. Darcy */ import java.lang.annotation.*; diff --git a/test/jdk/java/lang/Class/IsEnum.java b/test/jdk/java/lang/Class/IsEnum.java index fc0b0f7632b..3d2d9103ddb 100644 --- a/test/jdk/java/lang/Class/IsEnum.java +++ b/test/jdk/java/lang/Class/IsEnum.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 4891872 4989735 4990789 5020490 * @summary Check isEnum() method - * @author Joseph D. Darcy */ import java.lang.annotation.*; diff --git a/test/jdk/java/lang/Class/IsSynthetic.java b/test/jdk/java/lang/Class/IsSynthetic.java index d594f6303e1..1775b6bc11d 100644 --- a/test/jdk/java/lang/Class/IsSynthetic.java +++ b/test/jdk/java/lang/Class/IsSynthetic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 5012133 * @summary Check Class.isSynthetic method - * @author Joseph D. Darcy */ import java.lang.reflect.*; diff --git a/test/jdk/java/lang/Class/getEnclosingConstructor/EnclosingConstructorTests.java b/test/jdk/java/lang/Class/getEnclosingConstructor/EnclosingConstructorTests.java index ca128021e0c..c08f33af1e6 100644 --- a/test/jdk/java/lang/Class/getEnclosingConstructor/EnclosingConstructorTests.java +++ b/test/jdk/java/lang/Class/getEnclosingConstructor/EnclosingConstructorTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 4962341 6832557 * @summary Check getEnclosingMethod method - * @author Joseph D. Darcy */ import java.lang.reflect.Constructor; diff --git a/test/jdk/java/lang/Class/getEnclosingMethod/EnclosingMethodTests.java b/test/jdk/java/lang/Class/getEnclosingMethod/EnclosingMethodTests.java index 3a2a0910fc7..e890bb75d1e 100644 --- a/test/jdk/java/lang/Class/getEnclosingMethod/EnclosingMethodTests.java +++ b/test/jdk/java/lang/Class/getEnclosingMethod/EnclosingMethodTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 4962341 * @summary Check getEnclosingMethod method - * @author Joseph D. Darcy */ import java.lang.reflect.Method; diff --git a/test/jdk/java/lang/Double/BitwiseConversion.java b/test/jdk/java/lang/Double/BitwiseConversion.java index 381a7e9aed6..06e15d95575 100644 --- a/test/jdk/java/lang/Double/BitwiseConversion.java +++ b/test/jdk/java/lang/Double/BitwiseConversion.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,6 @@ * @library ../Math * @build DoubleConsts * @run main BitwiseConversion - * @author Joseph D. Darcy */ import static java.lang.Double.*; diff --git a/test/jdk/java/lang/Double/Constants.java b/test/jdk/java/lang/Double/Constants.java index 676630e12b9..e7aa5cbceb9 100644 --- a/test/jdk/java/lang/Double/Constants.java +++ b/test/jdk/java/lang/Double/Constants.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,6 @@ * @compile Constants.java * @bug 4397405 4826652 * @summary Testing constant-ness of Double.{MIN_VALUE, MAX_VALUE}, etc. - * @author Joseph D. Darcy */ public class Constants { diff --git a/test/jdk/java/lang/Double/Extrema.java b/test/jdk/java/lang/Double/Extrema.java index fef17100e0a..db9a10fb279 100644 --- a/test/jdk/java/lang/Double/Extrema.java +++ b/test/jdk/java/lang/Double/Extrema.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 4408489 4826652 * @summary Testing values of Double.{MIN_VALUE, MIN_NORMAL, MAX_VALUE} - * @author Joseph D. Darcy */ public class Extrema { diff --git a/test/jdk/java/lang/Double/NaNInfinityParsing.java b/test/jdk/java/lang/Double/NaNInfinityParsing.java index 846dcecd3b9..8b5d0e4888f 100644 --- a/test/jdk/java/lang/Double/NaNInfinityParsing.java +++ b/test/jdk/java/lang/Double/NaNInfinityParsing.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 4428772 * @summary Testing recognition of "NaN" and "Infinity" strings - * @author Joseph D. Darcy */ diff --git a/test/jdk/java/lang/Double/ParseHexFloatingPoint.java b/test/jdk/java/lang/Double/ParseHexFloatingPoint.java index a26a8b7a756..60fa13df75b 100644 --- a/test/jdk/java/lang/Double/ParseHexFloatingPoint.java +++ b/test/jdk/java/lang/Double/ParseHexFloatingPoint.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,6 @@ * @run main ParseHexFloatingPoint * @bug 4826774 8078672 * @summary Numerical tests for hexadecimal inputs to parse{Double, Float} (use -Dseed=X to set PRNG seed) - * @author Joseph D. Darcy * @key randomness */ diff --git a/test/jdk/java/lang/Double/ToHexString.java b/test/jdk/java/lang/Double/ToHexString.java index a9f07bba508..912835b7aeb 100644 --- a/test/jdk/java/lang/Double/ToHexString.java +++ b/test/jdk/java/lang/Double/ToHexString.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,6 @@ * @library ../Math * @build DoubleConsts * @run main ToHexString - * @author Joseph D. Darcy */ import java.util.regex.*; diff --git a/test/jdk/java/lang/Float/BitwiseConversion.java b/test/jdk/java/lang/Float/BitwiseConversion.java index 973e00e7008..9bb4a34a55b 100644 --- a/test/jdk/java/lang/Float/BitwiseConversion.java +++ b/test/jdk/java/lang/Float/BitwiseConversion.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,6 @@ * @library ../Math * @build FloatConsts * @run main BitwiseConversion - * @author Joseph D. Darcy */ import static java.lang.Float.*; diff --git a/test/jdk/java/lang/Float/Constants.java b/test/jdk/java/lang/Float/Constants.java index b6ad85ca0c2..47463fc5916 100644 --- a/test/jdk/java/lang/Float/Constants.java +++ b/test/jdk/java/lang/Float/Constants.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,6 @@ * @compile Constants.java * @bug 4397405 4826652 * @summary Testing constant-ness of Float.{MIN_VALUE, MAX_VALUE}, etc. - * @author Joseph D. Darcy */ public class Constants { diff --git a/test/jdk/java/lang/Float/Extrema.java b/test/jdk/java/lang/Float/Extrema.java index 869f22072e7..46447bfcb2f 100644 --- a/test/jdk/java/lang/Float/Extrema.java +++ b/test/jdk/java/lang/Float/Extrema.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 4408489 4826652 * @summary Testing values of Float.{MIN_VALUE, MIN_NORMAL, MAX_VALUE} - * @author Joseph D. Darcy */ public class Extrema { diff --git a/test/jdk/java/lang/Float/NaNInfinityParsing.java b/test/jdk/java/lang/Float/NaNInfinityParsing.java index 38a402a9775..6df42b376a5 100644 --- a/test/jdk/java/lang/Float/NaNInfinityParsing.java +++ b/test/jdk/java/lang/Float/NaNInfinityParsing.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 4428772 * @summary Testing recognition of "NaN" and "Infinity" strings - * @author Joseph D. Darcy */ diff --git a/test/jdk/java/lang/Integer/Decode.java b/test/jdk/java/lang/Integer/Decode.java index 42493221fe4..b5f881a0e9f 100644 --- a/test/jdk/java/lang/Integer/Decode.java +++ b/test/jdk/java/lang/Integer/Decode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,6 @@ * @test * @bug 4136371 5017980 6576055 * @summary Test Integer.decode method - * @author madbot - * @author Joseph D. Darcy */ /** diff --git a/test/jdk/java/lang/Integer/ParsingTest.java b/test/jdk/java/lang/Integer/ParsingTest.java index f5f64f70c84..24e1dd6f3aa 100644 --- a/test/jdk/java/lang/Integer/ParsingTest.java +++ b/test/jdk/java/lang/Integer/ParsingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 5017980 6576055 8041972 8055251 * @summary Test parsing methods - * @author Joseph D. Darcy */ import java.lang.IndexOutOfBoundsException; diff --git a/test/jdk/java/lang/Integer/Unsigned.java b/test/jdk/java/lang/Integer/Unsigned.java index 6c3aecc70c1..911f3f8fe8f 100644 --- a/test/jdk/java/lang/Integer/Unsigned.java +++ b/test/jdk/java/lang/Integer/Unsigned.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 4504839 4215269 6322074 * @summary Basic tests for unsigned operations. - * @author Joseph D. Darcy */ public class Unsigned { public static void main(String... args) { diff --git a/test/jdk/java/lang/Long/Decode.java b/test/jdk/java/lang/Long/Decode.java index d47f976e6fc..fc2762b1bc2 100644 --- a/test/jdk/java/lang/Long/Decode.java +++ b/test/jdk/java/lang/Long/Decode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,6 @@ * @test * @bug 4136371 5017980 6576055 * @summary Test Long.decode method - * @author madbot - * @author Joseph D. Darcy */ import java.math.BigInteger; diff --git a/test/jdk/java/lang/Long/ParsingTest.java b/test/jdk/java/lang/Long/ParsingTest.java index cbf83415d36..23d007dfd26 100644 --- a/test/jdk/java/lang/Long/ParsingTest.java +++ b/test/jdk/java/lang/Long/ParsingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 5017980 6576055 8041972 8055251 * @summary Test parsing methods - * @author Joseph D. Darcy */ /** diff --git a/test/jdk/java/lang/Long/Unsigned.java b/test/jdk/java/lang/Long/Unsigned.java index f6eeed534b8..aba66c72a92 100644 --- a/test/jdk/java/lang/Long/Unsigned.java +++ b/test/jdk/java/lang/Long/Unsigned.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 4504839 4215269 6322074 8030814 * @summary Basic tests for unsigned operations - * @author Joseph D. Darcy */ import java.math.*; diff --git a/test/jdk/java/lang/Short/Decode.java b/test/jdk/java/lang/Short/Decode.java index 8f76751b589..d63e911b710 100644 --- a/test/jdk/java/lang/Short/Decode.java +++ b/test/jdk/java/lang/Short/Decode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,8 +25,6 @@ * @test * @bug 4136371 5017980 6576055 * @summary Test Short.decode method - * @author madbot - * @author Joseph D. Darcy */ /** diff --git a/test/jdk/java/lang/Throwable/SuppressedExceptions.java b/test/jdk/java/lang/Throwable/SuppressedExceptions.java index f6fe09df4ef..157a4ffa99b 100644 --- a/test/jdk/java/lang/Throwable/SuppressedExceptions.java +++ b/test/jdk/java/lang/Throwable/SuppressedExceptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,6 @@ import java.util.*; * @test * @bug 6911258 6962571 6963622 6991528 7005628 8012044 * @summary Basic tests of suppressed exceptions - * @author Joseph D. Darcy */ public class SuppressedExceptions { diff --git a/test/jdk/java/lang/annotation/Missing/MissingTest.java b/test/jdk/java/lang/annotation/Missing/MissingTest.java index d8a1c44e7ee..10e3b436d12 100644 --- a/test/jdk/java/lang/annotation/Missing/MissingTest.java +++ b/test/jdk/java/lang/annotation/Missing/MissingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 6322301 5041778 * @summary Verify when missing annotation classes cause exceptions - * @author Joseph D. Darcy * @compile MissingTest.java A.java B.java C.java D.java Marker.java Missing.java MissingWrapper.java MissingDefault.java * @clean Missing * @run main MissingTest diff --git a/test/jdk/java/lang/annotation/TestIncompleteAnnotationExceptionNPE.java b/test/jdk/java/lang/annotation/TestIncompleteAnnotationExceptionNPE.java index 9e9e7a7a60a..390f0fc96bd 100644 --- a/test/jdk/java/lang/annotation/TestIncompleteAnnotationExceptionNPE.java +++ b/test/jdk/java/lang/annotation/TestIncompleteAnnotationExceptionNPE.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 7021922 * @summary Test null handling of IncompleteAnnotationException constructor - * @author Joseph D. Darcy */ import java.lang.annotation.*; diff --git a/test/jdk/java/lang/reflect/AnnotatedElement/TestAnnotatedElementDefaults.java b/test/jdk/java/lang/reflect/AnnotatedElement/TestAnnotatedElementDefaults.java index 97e9a79e14b..34c4f840241 100644 --- a/test/jdk/java/lang/reflect/AnnotatedElement/TestAnnotatedElementDefaults.java +++ b/test/jdk/java/lang/reflect/AnnotatedElement/TestAnnotatedElementDefaults.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 8005294 * @summary Check behavior of default methods of AnnotatedElement - * @author Joseph D. Darcy */ import java.lang.annotation.*; diff --git a/test/jdk/java/lang/reflect/Constructor/GenericStringTest.java b/test/jdk/java/lang/reflect/Constructor/GenericStringTest.java index 56a781fce18..a8c6c671d86 100644 --- a/test/jdk/java/lang/reflect/Constructor/GenericStringTest.java +++ b/test/jdk/java/lang/reflect/Constructor/GenericStringTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 5033583 6316717 6470106 8161500 8162539 6304578 * @summary Check toGenericString() and toString() methods - * @author Joseph D. Darcy */ import java.lang.reflect.*; diff --git a/test/jdk/java/lang/reflect/Constructor/TestParameterAnnotations.java b/test/jdk/java/lang/reflect/Constructor/TestParameterAnnotations.java index 5773825a8e2..7512d36cb42 100644 --- a/test/jdk/java/lang/reflect/Constructor/TestParameterAnnotations.java +++ b/test/jdk/java/lang/reflect/Constructor/TestParameterAnnotations.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 6332964 * @summary Verify getParameterAnnotations doesn't throw spurious errors - * @author Joseph D. Darcy */ import java.lang.reflect.*; diff --git a/test/jdk/java/lang/reflect/DefaultAccessibility.java b/test/jdk/java/lang/reflect/DefaultAccessibility.java index 6dce3e249c2..69f8946e617 100644 --- a/test/jdk/java/lang/reflect/DefaultAccessibility.java +++ b/test/jdk/java/lang/reflect/DefaultAccessibility.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 6648344 * @summary Test that default accessibility is false - * @author Joseph D. Darcy */ import java.lang.reflect.*; diff --git a/test/jdk/java/lang/reflect/Field/GenericStringTest.java b/test/jdk/java/lang/reflect/Field/GenericStringTest.java index 65fbbc43381..5b5c321a3e1 100644 --- a/test/jdk/java/lang/reflect/Field/GenericStringTest.java +++ b/test/jdk/java/lang/reflect/Field/GenericStringTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 5033583 8161500 * @summary Check toGenericString() method - * @author Joseph D. Darcy */ import java.lang.reflect.*; diff --git a/test/jdk/java/lang/reflect/Generics/HashCodeTest.java b/test/jdk/java/lang/reflect/Generics/HashCodeTest.java index 53fbad758d0..00e1494d04a 100644 --- a/test/jdk/java/lang/reflect/Generics/HashCodeTest.java +++ b/test/jdk/java/lang/reflect/Generics/HashCodeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 5097856 * @summary Computing hashCode of objects modeling generics shouldn't blow stack - * @author Joseph D. Darcy */ import java.util.*; diff --git a/test/jdk/java/lang/reflect/Generics/Probe.java b/test/jdk/java/lang/reflect/Generics/Probe.java index cbe94aef7a4..e14ed54f863 100644 --- a/test/jdk/java/lang/reflect/Generics/Probe.java +++ b/test/jdk/java/lang/reflect/Generics/Probe.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 5003916 6704655 6873951 6476261 8004928 * @summary Testing parsing of signatures attributes of nested classes - * @author Joseph D. Darcy */ import java.lang.reflect.*; diff --git a/test/jdk/java/lang/reflect/Generics/StringsAndBounds.java b/test/jdk/java/lang/reflect/Generics/StringsAndBounds.java index 6d7756b2163..5c44207bcc5 100644 --- a/test/jdk/java/lang/reflect/Generics/StringsAndBounds.java +++ b/test/jdk/java/lang/reflect/Generics/StringsAndBounds.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 5015676 4987888 4997464 * @summary Testing upper bounds and availability of toString methods - * @author Joseph D. Darcy */ import java.lang.reflect.*; diff --git a/test/jdk/java/lang/reflect/Generics/TestParameterizedType.java b/test/jdk/java/lang/reflect/Generics/TestParameterizedType.java index 6bb3aa47aef..99fc3db0c97 100644 --- a/test/jdk/java/lang/reflect/Generics/TestParameterizedType.java +++ b/test/jdk/java/lang/reflect/Generics/TestParameterizedType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 5061485 * @summary Test sematics of ParameterizedType.equals - * @author Joseph D. Darcy */ import java.util.*; diff --git a/test/jdk/java/lang/reflect/Generics/exceptionCauseTest.java b/test/jdk/java/lang/reflect/Generics/exceptionCauseTest.java index dc8397aded6..485e8d3c51e 100644 --- a/test/jdk/java/lang/reflect/Generics/exceptionCauseTest.java +++ b/test/jdk/java/lang/reflect/Generics/exceptionCauseTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 4981727 * @summary - * @author Joseph D. Darcy */ import java.io.PrintStream; diff --git a/test/jdk/java/lang/reflect/Generics/getAnnotationTest.java b/test/jdk/java/lang/reflect/Generics/getAnnotationTest.java index 0e1317e8d2d..766543863d0 100644 --- a/test/jdk/java/lang/reflect/Generics/getAnnotationTest.java +++ b/test/jdk/java/lang/reflect/Generics/getAnnotationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 4979440 * @summary Test for signature parsing corner case - * @author Joseph D. Darcy */ import java.lang.reflect.*; diff --git a/test/jdk/java/lang/reflect/Method/GenericStringTest.java b/test/jdk/java/lang/reflect/Method/GenericStringTest.java index c1c8e141f79..e7fe873d3cc 100644 --- a/test/jdk/java/lang/reflect/Method/GenericStringTest.java +++ b/test/jdk/java/lang/reflect/Method/GenericStringTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 5033583 6316717 6470106 8004979 8161500 8162539 6304578 * @summary Check toGenericString() and toString() methods - * @author Joseph D. Darcy */ import java.lang.reflect.*; diff --git a/test/jdk/java/lang/reflect/Method/IsDefaultTest.java b/test/jdk/java/lang/reflect/Method/IsDefaultTest.java index c48ebaf9e96..0c983a8b0ba 100644 --- a/test/jdk/java/lang/reflect/Method/IsDefaultTest.java +++ b/test/jdk/java/lang/reflect/Method/IsDefaultTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 8005042 * @summary Check behavior of Method.isDefault - * @author Joseph D. Darcy */ import java.lang.reflect.*; diff --git a/test/jdk/java/lang/reflect/Method/defaultMethodModeling/DefaultMethodModeling.java b/test/jdk/java/lang/reflect/Method/defaultMethodModeling/DefaultMethodModeling.java index 30eca409cea..b91f73ee845 100644 --- a/test/jdk/java/lang/reflect/Method/defaultMethodModeling/DefaultMethodModeling.java +++ b/test/jdk/java/lang/reflect/Method/defaultMethodModeling/DefaultMethodModeling.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 8011590 * @summary Check modeling of default methods - * @author Joseph D. Darcy */ import java.util.Objects; diff --git a/test/jdk/java/lang/reflect/TypeVariable/TestAnnotatedElement.java b/test/jdk/java/lang/reflect/TypeVariable/TestAnnotatedElement.java index 94f8d459cf0..9788eab3060 100644 --- a/test/jdk/java/lang/reflect/TypeVariable/TestAnnotatedElement.java +++ b/test/jdk/java/lang/reflect/TypeVariable/TestAnnotatedElement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 7086192 * @summary Verify functionality of AnnotatedElement methods on type variables - * @author Joseph D. Darcy */ import java.lang.reflect.*; diff --git a/test/jdk/java/math/BigDecimal/AddTests.java b/test/jdk/java/math/BigDecimal/AddTests.java index 8045e280435..d6f57366d2a 100644 --- a/test/jdk/java/math/BigDecimal/AddTests.java +++ b/test/jdk/java/math/BigDecimal/AddTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 6362557 8200698 * @summary Some tests of add(BigDecimal, mc) - * @author Joseph D. Darcy */ import java.math.*; diff --git a/test/jdk/java/math/BigDecimal/CompareToTests.java b/test/jdk/java/math/BigDecimal/CompareToTests.java index baefcc5b499..b6ae31bca80 100644 --- a/test/jdk/java/math/BigDecimal/CompareToTests.java +++ b/test/jdk/java/math/BigDecimal/CompareToTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 6473768 * @summary Tests of BigDecimal.compareTo - * @author Joseph D. Darcy */ import java.math.*; import static java.math.BigDecimal.*; diff --git a/test/jdk/java/math/BigDecimal/DivideTests.java b/test/jdk/java/math/BigDecimal/DivideTests.java index fe0fea73ff6..140271dc000 100644 --- a/test/jdk/java/math/BigDecimal/DivideTests.java +++ b/test/jdk/java/math/BigDecimal/DivideTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 4851776 4907265 6177836 6876282 8066842 * @summary Some tests for the divide methods. - * @author Joseph D. Darcy */ import java.math.*; diff --git a/test/jdk/java/math/BigDecimal/IntegralDivisionTests.java b/test/jdk/java/math/BigDecimal/IntegralDivisionTests.java index 9fab5bb28ae..7df63b6329f 100644 --- a/test/jdk/java/math/BigDecimal/IntegralDivisionTests.java +++ b/test/jdk/java/math/BigDecimal/IntegralDivisionTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,6 @@ * @test * @bug 4904082 4917089 6337226 6378503 * @summary Tests that integral division and related methods return the proper result and scale. - * @author Joseph D. Darcy */ import java.math.*; public class IntegralDivisionTests { diff --git a/test/jdk/java/math/BigDecimal/NegateTests.java b/test/jdk/java/math/BigDecimal/NegateTests.java index 5b570325e90..fc4ce82e286 100644 --- a/test/jdk/java/math/BigDecimal/NegateTests.java +++ b/test/jdk/java/math/BigDecimal/NegateTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 6325535 * @summary Test for the rounding behavior of negate(MathContext) - * @author Joseph D. Darcy */ import java.math.*; diff --git a/test/jdk/java/math/BigDecimal/PowTests.java b/test/jdk/java/math/BigDecimal/PowTests.java index 49fc74c8791..a552e981c2e 100644 --- a/test/jdk/java/math/BigDecimal/PowTests.java +++ b/test/jdk/java/math/BigDecimal/PowTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 4916097 * @summary Some exponent over/undeflow tests for the pow method - * @author Joseph D. Darcy */ import java.math.*; diff --git a/test/jdk/java/math/BigDecimal/PrecisionTests.java b/test/jdk/java/math/BigDecimal/PrecisionTests.java index 43df43e16bc..88d9843c724 100644 --- a/test/jdk/java/math/BigDecimal/PrecisionTests.java +++ b/test/jdk/java/math/BigDecimal/PrecisionTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 1234567 * @summary Test that precision() is computed properly. - * @author Joseph D. Darcy */ import java.math.*; diff --git a/test/jdk/java/math/BigDecimal/RoundingTests.java b/test/jdk/java/math/BigDecimal/RoundingTests.java index 95d579e791a..6a12124fd62 100644 --- a/test/jdk/java/math/BigDecimal/RoundingTests.java +++ b/test/jdk/java/math/BigDecimal/RoundingTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 6334849 * @summary Tests of dropping digits near the scale threshold - * @author Joseph D. Darcy */ import java.math.*; public class RoundingTests { diff --git a/test/jdk/java/math/BigDecimal/ScaleByPowerOfTenTests.java b/test/jdk/java/math/BigDecimal/ScaleByPowerOfTenTests.java index 638fce9ed54..93131b77be2 100644 --- a/test/jdk/java/math/BigDecimal/ScaleByPowerOfTenTests.java +++ b/test/jdk/java/math/BigDecimal/ScaleByPowerOfTenTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 4899722 * @summary Basic tests of scaleByPowerOfTen - * @author Joseph D. Darcy */ import java.math.*; diff --git a/test/jdk/java/math/BigDecimal/StrippingZerosTest.java b/test/jdk/java/math/BigDecimal/StrippingZerosTest.java index 083b4eabbf1..c79c26c0ce5 100644 --- a/test/jdk/java/math/BigDecimal/StrippingZerosTest.java +++ b/test/jdk/java/math/BigDecimal/StrippingZerosTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,6 @@ * @summary A few tests of stripTrailingZeros * @run main StrippingZerosTest * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+EliminateAutoBox -XX:AutoBoxCacheMax=20000 StrippingZerosTest - * @author Joseph D. Darcy */ import java.math.*; diff --git a/test/jdk/java/math/BigDecimal/ToPlainStringTests.java b/test/jdk/java/math/BigDecimal/ToPlainStringTests.java index 0a1f617c0e5..28d5cdcd89d 100644 --- a/test/jdk/java/math/BigDecimal/ToPlainStringTests.java +++ b/test/jdk/java/math/BigDecimal/ToPlainStringTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,6 @@ * @summary Basic tests of toPlainString method * @run main ToPlainStringTests * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+EliminateAutoBox -XX:AutoBoxCacheMax=20000 ToPlainStringTests - * @author Joseph D. Darcy */ import java.math.*; diff --git a/test/jdk/java/math/BigDecimal/ZeroScalingTests.java b/test/jdk/java/math/BigDecimal/ZeroScalingTests.java index 05a59150b13..908487d68ef 100644 --- a/test/jdk/java/math/BigDecimal/ZeroScalingTests.java +++ b/test/jdk/java/math/BigDecimal/ZeroScalingTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,6 @@ * @summary Tests that the scale of zero is propagated properly and has the * proper effect and that setting the scale to zero does not mutate the * BigDecimal. - * @author Joseph D. Darcy */ import java.math.*; diff --git a/test/jdk/java/math/BigInteger/CompareToTests.java b/test/jdk/java/math/BigInteger/CompareToTests.java index 4e549fa2a53..3d9ff40ce56 100644 --- a/test/jdk/java/math/BigInteger/CompareToTests.java +++ b/test/jdk/java/math/BigInteger/CompareToTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 6473768 * @summary Tests of BigInteger.compareTo - * @author Joseph D. Darcy */ import java.math.*; import static java.math.BigInteger.*; diff --git a/test/jdk/java/math/BigInteger/ExtremeShiftingTests.java b/test/jdk/java/math/BigInteger/ExtremeShiftingTests.java index 853b88668a2..a173d1cf6dd 100644 --- a/test/jdk/java/math/BigInteger/ExtremeShiftingTests.java +++ b/test/jdk/java/math/BigInteger/ExtremeShiftingTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,6 @@ * @summary Tests of shiftLeft and shiftRight on Integer.MIN_VALUE * @requires os.maxMemory >= 1g * @run main/othervm -Xmx512m ExtremeShiftingTests - * @author Joseph D. Darcy */ import java.math.BigInteger; import static java.math.BigInteger.*; diff --git a/test/jdk/java/math/BigInteger/OperatorNpeTests.java b/test/jdk/java/math/BigInteger/OperatorNpeTests.java index 2985ae00c8e..593e15445d5 100644 --- a/test/jdk/java/math/BigInteger/OperatorNpeTests.java +++ b/test/jdk/java/math/BigInteger/OperatorNpeTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 6365176 * @summary Get NullPointerExceptions when expected - * @author Joseph D. Darcy */ import java.math.*; diff --git a/test/jdk/java/math/BigInteger/StringConstructor.java b/test/jdk/java/math/BigInteger/StringConstructor.java index c8fd9f83c6b..aa95fd4e346 100644 --- a/test/jdk/java/math/BigInteger/StringConstructor.java +++ b/test/jdk/java/math/BigInteger/StringConstructor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 4489146 5017980 * @summary tests String constructors of BigInteger - * @author Joseph D. Darcy */ import java.math.*; diff --git a/test/jdk/java/math/BigInteger/TestValueExact.java b/test/jdk/java/math/BigInteger/TestValueExact.java index 63ee1583527..fcd934653be 100644 --- a/test/jdk/java/math/BigInteger/TestValueExact.java +++ b/test/jdk/java/math/BigInteger/TestValueExact.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 6371401 * @summary Tests of fooValueExact methods - * @author Joseph D. Darcy */ import java.math.BigInteger; diff --git a/test/jdk/java/math/RoundingMode/RoundingModeTests.java b/test/jdk/java/math/RoundingMode/RoundingModeTests.java index 87ecad945b6..6edccb9277d 100644 --- a/test/jdk/java/math/RoundingMode/RoundingModeTests.java +++ b/test/jdk/java/math/RoundingMode/RoundingModeTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ * @test * @bug 4851776 4891522 4905335 * @summary Basic tests for the RoundingMode class. - * @author Joseph D. Darcy */ import java.math.RoundingMode; diff --git a/test/jdk/tools/launcher/ChangeDataModel.java b/test/jdk/tools/launcher/ChangeDataModel.java index e6bc281ad62..14945045435 100644 --- a/test/jdk/tools/launcher/ChangeDataModel.java +++ b/test/jdk/tools/launcher/ChangeDataModel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,6 @@ * @compile -XDignore.symbol.file ChangeDataModel.java * @run main ChangeDataModel * @summary Verify -d32, -d64 and -J prefixed data-model options are rejected on all platforms - * @author Joseph D. Darcy, ksrini */ import java.util.Arrays; diff --git a/test/jdk/tools/launcher/I18NTest.java b/test/jdk/tools/launcher/I18NTest.java index aa1ce24e798..83d90f56327 100644 --- a/test/jdk/tools/launcher/I18NTest.java +++ b/test/jdk/tools/launcher/I18NTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,6 @@ * @compile -XDignore.symbol.file I18NTest.java * @run main I18NTest * @summary Test to see if class files with non-ASCII characters can be run - * @author Joseph D. Darcy, Kumar Srinivasan */ diff --git a/test/jdk/tools/launcher/UnresolvedExceptions.java b/test/jdk/tools/launcher/UnresolvedExceptions.java index ce14f405aed..6faa306c34c 100644 --- a/test/jdk/tools/launcher/UnresolvedExceptions.java +++ b/test/jdk/tools/launcher/UnresolvedExceptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,6 @@ * @compile -XDignore.symbol.file UnresolvedExceptions.java * @run main UnresolvedExceptions * @summary Verifying jvm won't segv if exception not available - * @author Joseph D. Darcy, ksrini */ import java.io.File; From 873666d157340b3b953ad869576afd30d4304610 Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Thu, 16 Oct 2025 16:53:47 +0000 Subject: [PATCH 0244/1639] 8369451: Debug agent support for USE_ITERATE_THROUGH_HEAP is broken and should be removed Reviewed-by: sspitsyn, amenkov --- .../share/native/libjdwp/debugInit.c | 11 +- .../share/native/libjdwp/util.c | 102 ++++-------------- .../share/native/libjdwp/util.h | 8 +- 3 files changed, 22 insertions(+), 99 deletions(-) diff --git a/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.c b/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.c index 73ea9a295e6..2bed6b6bb28 100644 --- a/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.c +++ b/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -890,8 +890,6 @@ printUsage(void) " everything = 0xfff")); TTY_MESSAGE(( - "debugflags=flags debug flags (bitmask) none\n" - " USE_ITERATE_THROUGH_HEAP 0x01\n" "\n" "Environment Variables\n" "---------------------\n" @@ -1192,13 +1190,6 @@ parseOptions(char *options) } /*LINTED*/ logflags = (unsigned)strtol(current, NULL, 0); - } else if (strcmp(buf, "debugflags") == 0) { - /*LINTED*/ - if (!get_tok(&str, current, (int)(end - current), ',')) { - goto syntax_error; - } - /*LINTED*/ - gdata->debugflags = (unsigned)strtol(current, NULL, 0); } else if ( strcmp(buf, "suspend")==0 ) { if ( !get_boolean(&str, &suspendOnInit) ) { goto syntax_error; diff --git a/src/jdk.jdwp.agent/share/native/libjdwp/util.c b/src/jdk.jdwp.agent/share/native/libjdwp/util.c index 45de2ba7b7a..980c622cc48 100644 --- a/src/jdk.jdwp.agent/share/native/libjdwp/util.c +++ b/src/jdk.jdwp.agent/share/native/libjdwp/util.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2730,10 +2730,6 @@ typedef struct ClassCountData { jvmtiError error; } ClassCountData; -/* Two different cbObjectCounter's, one for FollowReferences, one for - * IterateThroughHeap. Pick a card, any card. - */ - /* Callback for object count heap traversal (heap_reference_callback) */ static jint JNICALL cbObjectCounterFromRef(jvmtiHeapReferenceKind reference_kind, @@ -2795,38 +2791,6 @@ cbObjectCounterFromRef(jvmtiHeapReferenceKind reference_kind, return JVMTI_VISIT_OBJECTS; } -/* Callback for instance count heap traversal (heap_iteration_callback) */ -static jint JNICALL -cbObjectCounter(jlong class_tag, jlong size, jlong* tag_ptr, jint length, - void* user_data) -{ - ClassCountData *data; - int index; - - /* Check data structure */ - data = (ClassCountData*)user_data; - if (data == NULL) { - return JVMTI_VISIT_ABORT; - } - - /* Classes with no tag should be filtered out. */ - if ( class_tag == (jlong)0 ) { - data->error = AGENT_ERROR_INTERNAL; - return JVMTI_VISIT_ABORT; - } - - /* Class tag is actually an index into data arrays */ - index = CLASSTAG2INDEX(class_tag); - if (index < 0 || index >= data->classCount) { - data->error = AGENT_ERROR_ILLEGAL_ARGUMENT; - return JVMTI_VISIT_ABORT; - } - - /* Bump instance count on this class */ - data->counts[index]++; - return JVMTI_VISIT_OBJECTS; -} - /* Get instance counts for a set of classes */ jvmtiError classInstanceCounts(jint classCount, jclass *classes, jlong *counts) @@ -2879,53 +2843,27 @@ classInstanceCounts(jint classCount, jclass *classes, jlong *counts) /* Clear out callbacks structure */ (void)memset(&heap_callbacks,0,sizeof(heap_callbacks)); - /* Check debug flags to see how to do this. */ - if ( (gdata->debugflags & USE_ITERATE_THROUGH_HEAP) == 0 ) { + /* Using FollowReferences only gives us live objects, but we + * need to tag the objects to avoid counting them twice since + * the callback is per reference. + * The jclass objects have been tagged with their index in the + * supplied list, and that tag may flip to negative if it + * is also an object of interest. + * All other objects being counted that weren't in the + * supplied classes list will have a negative classCount + * tag value. So all objects counted will have negative tags. + * If the absolute tag value is an index in the supplied + * list, then it's one of the supplied classes. + */ + data.negObjTag = -INDEX2CLASSTAG(classCount); - /* Using FollowReferences only gives us live objects, but we - * need to tag the objects to avoid counting them twice since - * the callback is per reference. - * The jclass objects have been tagged with their index in the - * supplied list, and that tag may flip to negative if it - * is also an object of interest. - * All other objects being counted that weren't in the - * supplied classes list will have a negative classCount - * tag value. So all objects counted will have negative tags. - * If the absolute tag value is an index in the supplied - * list, then it's one of the supplied classes. - */ - data.negObjTag = -INDEX2CLASSTAG(classCount); + /* Setup callbacks, only using object reference callback */ + heap_callbacks.heap_reference_callback = &cbObjectCounterFromRef; - /* Setup callbacks, only using object reference callback */ - heap_callbacks.heap_reference_callback = &cbObjectCounterFromRef; - - /* Follow references, no initiating object, tagged classes only */ - error = JVMTI_FUNC_PTR(jvmti,FollowReferences) - (jvmti, JVMTI_HEAP_FILTER_CLASS_UNTAGGED, - NULL, NULL, &heap_callbacks, &data); - - } else { - - /* Using IterateThroughHeap means that we will visit each object - * once, so no special tag tricks here. Just simple counting. - * However in this case the object might not be live, so we do - * a GC beforehand to make sure we minimize this. - */ - - /* FIXUP: Need some kind of trigger here to avoid excessive GC's? */ - error = JVMTI_FUNC_PTR(jvmti,ForceGarbageCollection)(jvmti); - if ( error != JVMTI_ERROR_NONE ) { - - /* Setup callbacks, just need object callback */ - heap_callbacks.heap_iteration_callback = &cbObjectCounter; - - /* Iterate through entire heap, tagged classes only */ - error = JVMTI_FUNC_PTR(jvmti,IterateThroughHeap) - (jvmti, JVMTI_HEAP_FILTER_CLASS_UNTAGGED, - NULL, &heap_callbacks, &data); - - } - } + /* Follow references, no initiating object, tagged classes only */ + error = JVMTI_FUNC_PTR(jvmti,FollowReferences) + (jvmti, JVMTI_HEAP_FILTER_CLASS_UNTAGGED, + NULL, NULL, &heap_callbacks, &data); /* Use data error if needed */ if ( error == JVMTI_ERROR_NONE ) { diff --git a/src/jdk.jdwp.agent/share/native/libjdwp/util.h b/src/jdk.jdwp.agent/share/native/libjdwp/util.h index 3d499d7d569..a48c8ba2c09 100644 --- a/src/jdk.jdwp.agent/share/native/libjdwp/util.h +++ b/src/jdk.jdwp.agent/share/native/libjdwp/util.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -92,12 +92,6 @@ typedef struct { jboolean quiet; jboolean jvmti_data_dump; /* If true, then support JVMTI DATA_DUMP_REQUEST events. */ - /* Debug flags (bit mask) */ - int debugflags; - - /* Possible debug flags */ - #define USE_ITERATE_THROUGH_HEAP 0X001 - char * options; jclass classClass; From d7b525ab9980743cf0cab3e3daaa4ccb725bfea8 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Thu, 16 Oct 2025 16:58:38 +0000 Subject: [PATCH 0245/1639] 8364673: Remove duplicate font mapping for itcavantgarde in psfontj2d.properties Reviewed-by: azvegint, kizune --- src/java.desktop/share/conf/psfontj2d.properties | 1 - 1 file changed, 1 deletion(-) diff --git a/src/java.desktop/share/conf/psfontj2d.properties b/src/java.desktop/share/conf/psfontj2d.properties index 9efe8864428..8030a82bc4f 100644 --- a/src/java.desktop/share/conf/psfontj2d.properties +++ b/src/java.desktop/share/conf/psfontj2d.properties @@ -59,7 +59,6 @@ avantgarde_book_oblique=avantgarde_book_oblique avantgarde_demi_oblique=avantgarde_demi_oblique # itcavantgarde=avantgarde_book -itcavantgarde=avantgarde_book itcavantgarde_demi=avantgarde_demi itcavantgarde_oblique=avantgarde_book_oblique itcavantgarde_demi_oblique=avantgarde_demi_oblique From 844118a9d854459778f88d299b148c2288131344 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Thu, 16 Oct 2025 16:58:56 +0000 Subject: [PATCH 0246/1639] 8369146: java/awt/PrintJob/GetGraphicsTest.java: Parse Exception: Invalid or unrecognized bugid: 50510568367702 Reviewed-by: syan, azvegint, kizune, jdv --- test/jdk/java/awt/PrintJob/GetGraphicsTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/jdk/java/awt/PrintJob/GetGraphicsTest.java b/test/jdk/java/awt/PrintJob/GetGraphicsTest.java index 61abe37b66b..2fe82e57c5a 100644 --- a/test/jdk/java/awt/PrintJob/GetGraphicsTest.java +++ b/test/jdk/java/awt/PrintJob/GetGraphicsTest.java @@ -23,7 +23,7 @@ /* @test - @bug 50510568367702 + @bug 5051056 8367702 @key headful printer @summary PrintJob.getGraphics() should return null after PrintJob.end() is called. @run main GetGraphicsTest From d4472979c43d9825ed2d008dbaed26dbf6d36180 Mon Sep 17 00:00:00 2001 From: William Kemper Date: Thu, 16 Oct 2025 17:49:08 +0000 Subject: [PATCH 0247/1639] 8367709: GenShen: Dirty cards for objects that get promoted by safepoint that intervenes between allocation and stores Reviewed-by: ysr --- .../share/gc/shenandoah/shenandoahBarrierSet.cpp | 15 +++++++++++++-- .../gc/shenandoah/shenandoahMarkingContext.cpp | 8 ++++---- .../shenandoahMarkingContext.inline.hpp | 4 ++-- .../gc/shenandoah/shenandoahScanRemembered.cpp | 6 +++--- .../shenandoahScanRemembered.inline.hpp | 6 +++--- 5 files changed, 25 insertions(+), 14 deletions(-) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp index 5d19a6a34e3..f6733d4a923 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp @@ -89,8 +89,19 @@ bool ShenandoahBarrierSet::need_keep_alive_barrier(DecoratorSet decorators, Basi void ShenandoahBarrierSet::on_slowpath_allocation_exit(JavaThread* thread, oop new_obj) { #if COMPILER2_OR_JVMCI - assert(!ReduceInitialCardMarks || !ShenandoahCardBarrier || ShenandoahGenerationalHeap::heap()->is_in_young(new_obj), - "Allocating new object outside of young generation: " INTPTR_FORMAT, p2i(new_obj)); + if (ReduceInitialCardMarks && ShenandoahCardBarrier && !ShenandoahHeap::heap()->is_in_young(new_obj)) { + log_debug(gc)("Newly allocated object (" PTR_FORMAT ") is not in the young generation", p2i(new_obj)); + // This can happen when an object is newly allocated, but we come to a safepoint before returning + // the object. If the safepoint runs a degenerated cycle that is upgraded to a full GC, this object + // will have survived two GC cycles. If the tenuring age is very low (1), this object may be promoted. + // In this case, we have an allocated object, but it has received no stores yet. If card marking barriers + // have been elided, we could end up with an object in old holding pointers to young that won't be in + // the remembered set. The solution here is conservative, but this problem should be rare, and it will + // correct itself on subsequent cycles when the remembered set is updated. + ShenandoahGenerationalHeap::heap()->old_generation()->card_scan()->mark_range_as_dirty( + cast_from_oop(new_obj), new_obj->size() + ); + } #endif // COMPILER2_OR_JVMCI assert(thread->deferred_card_mark().is_empty(), "We don't use this"); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.cpp b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.cpp index 0babeaffd3e..40eee8c342b 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.cpp @@ -74,8 +74,8 @@ void ShenandoahMarkingContext::initialize_top_at_mark_start(ShenandoahHeapRegion _top_at_mark_starts_base[idx] = bottom; _top_bitmaps[idx] = bottom; - log_debug(gc)("SMC:initialize_top_at_mark_start for Region %zu, TAMS: " PTR_FORMAT ", TopOfBitMap: " PTR_FORMAT, - r->index(), p2i(bottom), p2i(r->end())); + log_debug(gc, mark)("SMC:initialize_top_at_mark_start for Region %zu, TAMS: " PTR_FORMAT ", TopOfBitMap: " PTR_FORMAT, + r->index(), p2i(bottom), p2i(r->end())); } HeapWord* ShenandoahMarkingContext::top_bitmap(ShenandoahHeapRegion* r) { @@ -86,8 +86,8 @@ void ShenandoahMarkingContext::clear_bitmap(ShenandoahHeapRegion* r) { HeapWord* bottom = r->bottom(); HeapWord* top_bitmap = _top_bitmaps[r->index()]; - log_debug(gc)("SMC:clear_bitmap for %s Region %zu, top_bitmap: " PTR_FORMAT, - r->affiliation_name(), r->index(), p2i(top_bitmap)); + log_debug(gc, mark)("SMC:clear_bitmap for %s Region %zu, top_bitmap: " PTR_FORMAT, + r->affiliation_name(), r->index(), p2i(top_bitmap)); if (top_bitmap > bottom) { _mark_bit_map.clear_range_large(MemRegion(bottom, top_bitmap)); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.inline.hpp index e3ba774283c..bff4afc9ce9 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahMarkingContext.inline.hpp @@ -104,8 +104,8 @@ inline void ShenandoahMarkingContext::capture_top_at_mark_start(ShenandoahHeapRe "Region %zu, bitmap should be clear while adjusting TAMS: " PTR_FORMAT " -> " PTR_FORMAT, idx, p2i(old_tams), p2i(new_tams)); - log_debug(gc)("Capturing TAMS for %s Region %zu, was: " PTR_FORMAT ", now: " PTR_FORMAT, - r->affiliation_name(), idx, p2i(old_tams), p2i(new_tams)); + log_debug(gc, mark)("Capturing TAMS for %s Region %zu, was: " PTR_FORMAT ", now: " PTR_FORMAT, + r->affiliation_name(), idx, p2i(old_tams), p2i(new_tams)); _top_at_mark_starts_base[idx] = new_tams; _top_bitmaps[idx] = new_tams; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.cpp b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.cpp index 23c705348c4..4a0215f15f1 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.cpp @@ -683,9 +683,9 @@ void ShenandoahScanRememberedTask::do_work(uint worker_id) { struct ShenandoahRegionChunk assignment; while (_work_list->next(&assignment)) { ShenandoahHeapRegion* region = assignment._r; - log_debug(gc)("ShenandoahScanRememberedTask::do_work(%u), processing slice of region " - "%zu at offset %zu, size: %zu", - worker_id, region->index(), assignment._chunk_offset, assignment._chunk_size); + log_debug(gc, remset)("ShenandoahScanRememberedTask::do_work(%u), processing slice of region " + "%zu at offset %zu, size: %zu", + worker_id, region->index(), assignment._chunk_offset, assignment._chunk_size); if (region->is_old()) { size_t cluster_size = CardTable::card_size_in_words() * ShenandoahCardCluster::CardsPerCluster; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.inline.hpp index ce7cda98412..919cc4f6fd7 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahScanRemembered.inline.hpp @@ -343,9 +343,9 @@ ShenandoahScanRemembered::process_region_slice(ShenandoahHeapRegion *region, siz } } - log_debug(gc)("Remembered set scan processing Region %zu, from " PTR_FORMAT " to " PTR_FORMAT ", using %s table", - region->index(), p2i(start_of_range), p2i(end_of_range), - use_write_table? "read/write (updating)": "read (marking)"); + log_debug(gc, remset)("Remembered set scan processing Region %zu, from " PTR_FORMAT " to " PTR_FORMAT ", using %s table", + region->index(), p2i(start_of_range), p2i(end_of_range), + use_write_table? "read/write (updating)": "read (marking)"); // Note that end_of_range may point to the middle of a cluster because we limit scanning to // region->top() or region->get_update_watermark(). We avoid processing past end_of_range. From 9589a29d2515888b437d382204df22d01d4266ff Mon Sep 17 00:00:00 2001 From: Mikael Vidstedt Date: Thu, 16 Oct 2025 19:43:44 +0000 Subject: [PATCH 0248/1639] 8355752: Bump minimum boot jdk to JDK 25 Reviewed-by: darcy, shade, ihse, iris --- make/conf/github-actions.conf | 20 ++++++++++---------- make/conf/jib-profiles.js | 4 ++-- make/conf/version-numbers.conf | 2 +- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/make/conf/github-actions.conf b/make/conf/github-actions.conf index 74a830cbcc2..bd73e909062 100644 --- a/make/conf/github-actions.conf +++ b/make/conf/github-actions.conf @@ -29,21 +29,21 @@ GTEST_VERSION=1.14.0 JTREG_VERSION=8.1+1 LINUX_X64_BOOT_JDK_EXT=tar.gz -LINUX_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk24/1f9ff9062db4449d8ca828c504ffae90/36/GPL/openjdk-24_linux-x64_bin.tar.gz -LINUX_X64_BOOT_JDK_SHA256=88b090fa80c6c1d084ec9a755233967458788e2c0777ae2e172230c5c692d7ef +LINUX_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk25/bd75d5f9689641da8e1daabeccb5528b/36/GPL/openjdk-25_linux-x64_bin.tar.gz +LINUX_X64_BOOT_JDK_SHA256=59cdcaf255add4721de38eb411d4ecfe779356b61fb671aee63c7dec78054c2b ALPINE_LINUX_X64_BOOT_JDK_EXT=tar.gz -ALPINE_LINUX_X64_BOOT_JDK_URL=https://github.com/adoptium/temurin24-binaries/releases/download/jdk-24%2B36/OpenJDK24U-jdk_x64_alpine-linux_hotspot_24_36.tar.gz -ALPINE_LINUX_X64_BOOT_JDK_SHA256=a642608f0da78344ee6812fb1490b8bc1d7ad5a18064c70994d6f330568c51cb +ALPINE_LINUX_X64_BOOT_JDK_URL=https://github.com/adoptium/temurin25-binaries/releases/download/jdk-25%2B36/OpenJDK25U-jdk_x64_alpine-linux_hotspot_25_36.tar.gz +ALPINE_LINUX_X64_BOOT_JDK_SHA256=637e47474d411ed86134f413af7d5fef4180ddb0bf556347b7e74a88cf8904c8 MACOS_AARCH64_BOOT_JDK_EXT=tar.gz -MACOS_AARCH64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk24/1f9ff9062db4449d8ca828c504ffae90/36/GPL/openjdk-24_macos-aarch64_bin.tar.gz -MACOS_AARCH64_BOOT_JDK_SHA256=f7133238a12714a62c5ad2bd4da6741130be1a82512065da9ca23dee26b2d3d3 +MACOS_AARCH64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk25/bd75d5f9689641da8e1daabeccb5528b/36/GPL/openjdk-25_macos-aarch64_bin.tar.gz +MACOS_AARCH64_BOOT_JDK_SHA256=2006337bf326fdfdf6117081751ba38c1c8706d63419ecac7ff102ff7c776876 MACOS_X64_BOOT_JDK_EXT=tar.gz -MACOS_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk24/1f9ff9062db4449d8ca828c504ffae90/36/GPL/openjdk-24_macos-x64_bin.tar.gz -MACOS_X64_BOOT_JDK_SHA256=6bbfb1d01741cbe55ab90299cb91464b695de9a3ace85c15131aa2f50292f321 +MACOS_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk25/bd75d5f9689641da8e1daabeccb5528b/36/GPL/openjdk-25_macos-x64_bin.tar.gz +MACOS_X64_BOOT_JDK_SHA256=47482ad9888991ecac9b2bcc131e2b53ff78aff275104cef85f66252308e8a09 WINDOWS_X64_BOOT_JDK_EXT=zip -WINDOWS_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk24/1f9ff9062db4449d8ca828c504ffae90/36/GPL/openjdk-24_windows-x64_bin.zip -WINDOWS_X64_BOOT_JDK_SHA256=11d1d9f6ac272d5361c8a0bef01894364081c7fb1a6914c2ad2fc312ae83d63b +WINDOWS_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk25/bd75d5f9689641da8e1daabeccb5528b/36/GPL/openjdk-25_windows-x64_bin.zip +WINDOWS_X64_BOOT_JDK_SHA256=85bcc178461e2cb3c549ab9ca9dfa73afd54c09a175d6510d0884071867137d3 diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js index 9706321d7b6..795335d7c3c 100644 --- a/make/conf/jib-profiles.js +++ b/make/conf/jib-profiles.js @@ -387,8 +387,8 @@ var getJibProfilesCommon = function (input, data) { }; }; - common.boot_jdk_version = "24"; - common.boot_jdk_build_number = "36"; + common.boot_jdk_version = "25"; + common.boot_jdk_build_number = "37"; common.boot_jdk_home = input.get("boot_jdk", "install_path") + "/jdk-" + common.boot_jdk_version + (input.build_os == "macosx" ? ".jdk/Contents/Home" : ""); diff --git a/make/conf/version-numbers.conf b/make/conf/version-numbers.conf index 38d6e42dff9..977809535ba 100644 --- a/make/conf/version-numbers.conf +++ b/make/conf/version-numbers.conf @@ -37,6 +37,6 @@ DEFAULT_VERSION_DATE=2026-03-17 DEFAULT_VERSION_CLASSFILE_MAJOR=70 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`" DEFAULT_VERSION_CLASSFILE_MINOR=0 DEFAULT_VERSION_DOCS_API_SINCE=11 -DEFAULT_ACCEPTABLE_BOOT_VERSIONS="24 25 26" +DEFAULT_ACCEPTABLE_BOOT_VERSIONS="25 26" DEFAULT_JDK_SOURCE_TARGET_VERSION=26 DEFAULT_PROMOTED_VERSION_PRE=ea From 3248aaf3c4f6784d5176e2a2c5bac0fbda47ee6b Mon Sep 17 00:00:00 2001 From: Chen Liang Date: Thu, 16 Oct 2025 19:45:57 +0000 Subject: [PATCH 0249/1639] 8356548: Use ClassFile API instead of ASM to transform classes in tests Reviewed-by: sspitsyn, lmesnik, coleenp, iklam --- .../calls/common/InvokeDynamicPatcher.java | 215 ++++++++---------- .../CompiledInvokeDynamic2CompiledTest.java | 2 +- ...CompiledInvokeDynamic2InterpretedTest.java | 2 +- .../CompiledInvokeDynamic2NativeTest.java | 2 +- ...InterpretedInvokeDynamic2CompiledTest.java | 2 +- ...erpretedInvokeDynamic2InterpretedTest.java | 2 +- .../InterpretedInvokeDynamic2NativeTest.java | 2 +- ...fineMethodUsedByMultipleMethodHandles.java | 42 ++-- .../compiler/jvmci/common/CTVMUtilities.java | 125 +++++----- .../jtreg/runtime/MirrorFrame/Asmator.java | 47 ++-- .../runtime/MirrorFrame/Test8003720.java | 1 - .../MissedStackMapFrames.java | 45 ++-- .../RedefineClasses/RedefineAnnotations.java | 75 ++---- .../RedefineGenericSignatureTest.java | 30 ++- .../jvmti/RedefineClasses/RedefineObject.java | 46 +--- .../RedefineRetransform.java | 86 +++---- .../gc/g1/unloading/GenClassPoolJar.java | 35 +-- .../TestDescription.java | 1 - .../TestDescription.java | 1 - .../TestDescription.java | 1 - .../TestDescription.java | 1 - .../TestDescription.java | 1 - .../TestDescription.java | 1 - .../nsk/jvmti/GetClassFields/getclfld007.java | 57 ++--- 24 files changed, 306 insertions(+), 516 deletions(-) diff --git a/test/hotspot/jtreg/compiler/calls/common/InvokeDynamicPatcher.java b/test/hotspot/jtreg/compiler/calls/common/InvokeDynamicPatcher.java index b82e06317d2..d5c93ebaf5e 100644 --- a/test/hotspot/jtreg/compiler/calls/common/InvokeDynamicPatcher.java +++ b/test/hotspot/jtreg/compiler/calls/common/InvokeDynamicPatcher.java @@ -23,150 +23,121 @@ package compiler.calls.common; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.Handle; -import org.objectweb.asm.Label; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; - -import java.io.FileInputStream; import java.io.IOException; +import java.lang.classfile.ClassFile; +import java.lang.classfile.ClassTransform; +import java.lang.classfile.CodeBuilder; +import java.lang.classfile.CodeElement; +import java.lang.classfile.CodeTransform; +import java.lang.classfile.Label; +import java.lang.constant.ClassDesc; +import java.lang.constant.DirectMethodHandleDesc; +import java.lang.constant.DynamicCallSiteDesc; +import java.lang.constant.MethodHandleDesc; +import java.lang.constant.MethodTypeDesc; import java.lang.invoke.CallSite; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.net.URISyntaxException; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.nio.file.StandardOpenOption; +import static java.lang.constant.ConstantDescs.*; + /** * A class which patch InvokeDynamic class bytecode with invokydynamic instruction, rewriting "caller" method to call "callee" method using invokedynamic */ -public class InvokeDynamicPatcher extends ClassVisitor { +public final class InvokeDynamicPatcher { - private static final String CLASS = InvokeDynamic.class.getName() - .replace('.', '/'); + private static final ClassDesc CLASS = InvokeDynamic.class.describeConstable().orElseThrow(); private static final String CALLER_METHOD_NAME = "caller"; private static final String CALLEE_METHOD_NAME = "callee"; private static final String NATIVE_CALLEE_METHOD_NAME = "calleeNative"; private static final String BOOTSTRAP_METHOD_NAME = "bootstrapMethod"; private static final String CALL_NATIVE_FIELD = "nativeCallee"; - private static final String CALL_NATIVE_FIELD_DESC = "Z"; - private static final String CALLEE_METHOD_DESC - = "(L" + CLASS + ";IJFDLjava/lang/String;)Z"; - private static final String ASSERTTRUE_METHOD_DESC - = "(ZLjava/lang/String;)V"; - private static final String ASSERTS_CLASS = "jdk/test/lib/Asserts"; + private static final ClassDesc CALL_NATIVE_FIELD_DESC = CD_boolean; + private static final MethodTypeDesc CALLEE_METHOD_DESC = MethodTypeDesc.of( + CD_boolean, CLASS, CD_int, CD_long, CD_float, CD_double, CD_String); + private static final MethodTypeDesc ASSERTTRUE_METHOD_DESC = MethodTypeDesc.of( + CD_void, CD_boolean, CD_String); + private static final ClassDesc ASSERTS_CLASS = ClassDesc.ofInternalName("jdk/test/lib/Asserts"); private static final String ASSERTTRUE_METHOD_NAME = "assertTrue"; - public static void main(String args[]) { - ClassReader cr; - Path filePath; - try { - filePath = Paths.get(InvokeDynamic.class.getProtectionDomain().getCodeSource() - .getLocation().toURI()).resolve(CLASS + ".class"); - } catch (URISyntaxException ex) { - throw new Error("TESTBUG: Can't get code source" + ex, ex); - } - try (FileInputStream fis = new FileInputStream(filePath.toFile())) { - cr = new ClassReader(fis); - } catch (IOException e) { - throw new Error("Error reading file", e); - } - ClassWriter cw = new ClassWriter(cr, - ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS); - cr.accept(new InvokeDynamicPatcher(Opcodes.ASM5, cw), 0); - try { - Files.write(filePath, cw.toByteArray(), - StandardOpenOption.WRITE); - } catch (IOException e) { - throw new Error(e); - } - } + public static void main(String args[]) throws IOException, URISyntaxException { + Path filePath = Path.of(InvokeDynamic.class.getProtectionDomain().getCodeSource() + .getLocation().toURI()).resolve(InvokeDynamic.class.getName().replace('.', '/') +".class"); + var bytes = ClassFile.of().transformClass(ClassFile.of().parse(filePath), + ClassTransform.transformingMethodBodies(m -> m.methodName().equalsString(CALLER_METHOD_NAME), new CodeTransform() { + @Override + public void accept(CodeBuilder builder, CodeElement element) { + // discard + } - public InvokeDynamicPatcher(int api, ClassWriter cw) { - super(api, cw); - } - - @Override - public MethodVisitor visitMethod(final int access, final String name, - final String desc, final String signature, - final String[] exceptions) { - /* a code generate looks like - * 0: aload_0 - * 1: ldc #125 // int 1 - * 3: ldc2_w #126 // long 2l - * 6: ldc #128 // float 3.0f - * 8: ldc2_w #129 // double 4.0d - * 11: ldc #132 // String 5 - * 13: aload_0 - * 14: getfield #135 // Field nativeCallee:Z - * 17: ifeq 28 - * 20: invokedynamic #181, 0 // InvokeDynamic #1:calleeNative:(Lcompiler/calls/common/InvokeDynamic;IJFDLjava/lang/String;)Z - * 25: goto 33 - * 28: invokedynamic #183, 0 // InvokeDynamic #1:callee:(Lcompiler/calls/common/InvokeDynamic;IJFDLjava/lang/String;)Z - * 33: ldc #185 // String Call insuccessfull - * 35: invokestatic #191 // Method jdk/test/lib/Asserts.assertTrue:(ZLjava/lang/String;)V - * 38: return - * - * or, using java-like pseudo-code - * if (this.nativeCallee == false) { - * invokedynamic-call-return-value = invokedynamic-of-callee - * } else { - * invokedynamic-call-return-value = invokedynamic-of-nativeCallee - * } - * Asserts.assertTrue(invokedynamic-call-return-value, error-message); - * return; - */ - if (name.equals(CALLER_METHOD_NAME)) { - MethodVisitor mv = cv.visitMethod(access, name, desc, - signature, exceptions); - Label nonNativeLabel = new Label(); - Label checkLabel = new Label(); - MethodType mtype = MethodType.methodType(CallSite.class, - MethodHandles.Lookup.class, String.class, MethodType.class); - Handle bootstrap = new Handle(Opcodes.H_INVOKESTATIC, CLASS, - BOOTSTRAP_METHOD_NAME, mtype.toMethodDescriptorString()); - mv.visitCode(); - // push callee parameters onto stack - mv.visitVarInsn(Opcodes.ALOAD, 0);//push "this" - mv.visitLdcInsn(1); - mv.visitLdcInsn(2L); - mv.visitLdcInsn(3.0f); - mv.visitLdcInsn(4.0d); - mv.visitLdcInsn("5"); - // params loaded. let's decide what method to call - mv.visitVarInsn(Opcodes.ALOAD, 0); // push "this" - // get nativeCallee field - mv.visitFieldInsn(Opcodes.GETFIELD, CLASS, CALL_NATIVE_FIELD, - CALL_NATIVE_FIELD_DESC); - // if nativeCallee == false goto nonNativeLabel - mv.visitJumpInsn(Opcodes.IFEQ, nonNativeLabel); - // invokedynamic nativeCalleeMethod using bootstrap method - mv.visitInvokeDynamicInsn(NATIVE_CALLEE_METHOD_NAME, - CALLEE_METHOD_DESC, bootstrap); - // goto checkLabel - mv.visitJumpInsn(Opcodes.GOTO, checkLabel); - // label: nonNativeLabel - mv.visitLabel(nonNativeLabel); - // invokedynamic calleeMethod using bootstrap method - mv.visitInvokeDynamicInsn(CALLEE_METHOD_NAME, CALLEE_METHOD_DESC, - bootstrap); - mv.visitLabel(checkLabel); - mv.visitLdcInsn(CallsBase.CALL_ERR_MSG); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, ASSERTS_CLASS, - ASSERTTRUE_METHOD_NAME, ASSERTTRUE_METHOD_DESC, false); - // label: return - mv.visitInsn(Opcodes.RETURN); - mv.visitMaxs(0, 0); - mv.visitEnd(); - return null; - } - return super.visitMethod(access, name, desc, signature, exceptions); + /* the code generated looks like + * 0: aload_0 + * 1: ldc #125 // int 1 + * 3: ldc2_w #126 // long 2l + * 6: ldc #128 // float 3.0f + * 8: ldc2_w #129 // double 4.0d + * 11: ldc #132 // String 5 + * 13: aload_0 + * 14: getfield #135 // Field nativeCallee:Z + * 17: ifeq 28 + * 20: invokedynamic #181, 0 // InvokeDynamic #1:calleeNative:(Lcompiler/calls/common/InvokeDynamic;IJFDLjava/lang/String;)Z + * 25: goto 33 + * 28: invokedynamic #183, 0 // InvokeDynamic #1:callee:(Lcompiler/calls/common/InvokeDynamic;IJFDLjava/lang/String;)Z + * 33: ldc #185 // String Call insuccessfull + * 35: invokestatic #191 // Method jdk/test/lib/Asserts.assertTrue:(ZLjava/lang/String;)V + * 38: return + * + * or, using java-like pseudo-code + * if (this.nativeCallee == false) { + * invokedynamic-call-return-value = invokedynamic-of-callee + * } else { + * invokedynamic-call-return-value = invokedynamic-of-nativeCallee + * } + * Asserts.assertTrue(invokedynamic-call-return-value, error-message); + * return; + */ + @Override + public void atEnd(CodeBuilder builder) { + Label nonNativeLabel = builder.newLabel(); + Label checkLabel = builder.newLabel(); + MethodType mtype = MethodType.methodType(CallSite.class, + MethodHandles.Lookup.class, String.class, MethodType.class); + DirectMethodHandleDesc dmh = MethodHandleDesc.of(DirectMethodHandleDesc.Kind.STATIC, + CLASS, BOOTSTRAP_METHOD_NAME, mtype.descriptorString()); + // push callee parameters onto stack + builder.aload(builder.receiverSlot()) + .ldc(1) + .ldc(2L) + .ldc(3.0f) + .ldc(4.0d) + .ldc("5") + // params loaded. let's decide what method to call + .aload(builder.receiverSlot()) + // get nativeCallee field + .getfield(CLASS, CALL_NATIVE_FIELD, CALL_NATIVE_FIELD_DESC) + // if nativeCallee == false goto nonNativeLabel + .ifeq(nonNativeLabel) + // invokedynamic nativeCalleeMethod using bootstrap method + .invokedynamic(DynamicCallSiteDesc.of(dmh, NATIVE_CALLEE_METHOD_NAME, CALLEE_METHOD_DESC)) + // goto checkLabel + .goto_(checkLabel) + // label: nonNativeLabel + .labelBinding(nonNativeLabel) + // invokedynamic calleeMethod using bootstrap method + .invokedynamic(DynamicCallSiteDesc.of(dmh, CALLEE_METHOD_NAME, CALLEE_METHOD_DESC)) + .labelBinding(checkLabel) + .ldc(CallsBase.CALL_ERR_MSG) + .invokestatic(ASSERTS_CLASS, ASSERTTRUE_METHOD_NAME, ASSERTTRUE_METHOD_DESC) + // label: return + .return_(); + } + })); + Files.write(filePath, bytes, StandardOpenOption.WRITE); } } diff --git a/test/hotspot/jtreg/compiler/calls/fromCompiled/CompiledInvokeDynamic2CompiledTest.java b/test/hotspot/jtreg/compiler/calls/fromCompiled/CompiledInvokeDynamic2CompiledTest.java index 914500a25d4..c20f8f44822 100644 --- a/test/hotspot/jtreg/compiler/calls/fromCompiled/CompiledInvokeDynamic2CompiledTest.java +++ b/test/hotspot/jtreg/compiler/calls/fromCompiled/CompiledInvokeDynamic2CompiledTest.java @@ -25,10 +25,10 @@ * @test * @summary check calls from compiled to compiled using InvokeDynamic * @library /test/lib / - * @library /testlibrary/asm * @modules java.base/jdk.internal.misc * * @build jdk.test.whitebox.WhiteBox + * @build compiler.calls.common.InvokeDynamic * @run driver compiler.calls.common.InvokeDynamicPatcher * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. diff --git a/test/hotspot/jtreg/compiler/calls/fromCompiled/CompiledInvokeDynamic2InterpretedTest.java b/test/hotspot/jtreg/compiler/calls/fromCompiled/CompiledInvokeDynamic2InterpretedTest.java index b6f8520a90a..ee497d10707 100644 --- a/test/hotspot/jtreg/compiler/calls/fromCompiled/CompiledInvokeDynamic2InterpretedTest.java +++ b/test/hotspot/jtreg/compiler/calls/fromCompiled/CompiledInvokeDynamic2InterpretedTest.java @@ -25,10 +25,10 @@ * @test * @summary check calls from compiled to interpreted using InvokeDynamic * @library /test/lib / - * @library /testlibrary/asm * @modules java.base/jdk.internal.misc * * @build jdk.test.whitebox.WhiteBox + * @build compiler.calls.common.InvokeDynamic * @run driver compiler.calls.common.InvokeDynamicPatcher * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. diff --git a/test/hotspot/jtreg/compiler/calls/fromCompiled/CompiledInvokeDynamic2NativeTest.java b/test/hotspot/jtreg/compiler/calls/fromCompiled/CompiledInvokeDynamic2NativeTest.java index e334f6a15f0..7dc2b423587 100644 --- a/test/hotspot/jtreg/compiler/calls/fromCompiled/CompiledInvokeDynamic2NativeTest.java +++ b/test/hotspot/jtreg/compiler/calls/fromCompiled/CompiledInvokeDynamic2NativeTest.java @@ -25,10 +25,10 @@ * @test * @summary check calls from compiled to native using InvokeDynamic * @library /test/lib / - * @library /testlibrary/asm * @modules java.base/jdk.internal.misc * * @build jdk.test.whitebox.WhiteBox + * @build compiler.calls.common.InvokeDynamic * @run driver compiler.calls.common.InvokeDynamicPatcher * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. diff --git a/test/hotspot/jtreg/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2CompiledTest.java b/test/hotspot/jtreg/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2CompiledTest.java index ca626fd3b01..0ba1dd1a496 100644 --- a/test/hotspot/jtreg/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2CompiledTest.java +++ b/test/hotspot/jtreg/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2CompiledTest.java @@ -25,10 +25,10 @@ * @test * @summary check calls from interpreted to compiled using InvokeDynamic * @library /test/lib / - * @library /testlibrary/asm * @modules java.base/jdk.internal.misc * * @build jdk.test.whitebox.WhiteBox + * @build compiler.calls.common.InvokeDynamic * @run driver compiler.calls.common.InvokeDynamicPatcher * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. diff --git a/test/hotspot/jtreg/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2InterpretedTest.java b/test/hotspot/jtreg/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2InterpretedTest.java index d8d877977d4..7ed8c683629 100644 --- a/test/hotspot/jtreg/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2InterpretedTest.java +++ b/test/hotspot/jtreg/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2InterpretedTest.java @@ -25,10 +25,10 @@ * @test * @summary check calls from interpreted to interpreted using InvokeDynamic * @library /test/lib / - * @library /testlibrary/asm * @modules java.base/jdk.internal.misc * * @build jdk.test.whitebox.WhiteBox + * @build compiler.calls.common.InvokeDynamic * @run driver compiler.calls.common.InvokeDynamicPatcher * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. diff --git a/test/hotspot/jtreg/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2NativeTest.java b/test/hotspot/jtreg/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2NativeTest.java index 38bca4939d4..20f94db80b1 100644 --- a/test/hotspot/jtreg/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2NativeTest.java +++ b/test/hotspot/jtreg/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2NativeTest.java @@ -25,10 +25,10 @@ * @test * @summary check calls from interpreted to native using InvokeDynamic * @library /test/lib / - * @library /testlibrary/asm * @modules java.base/jdk.internal.misc * * @build jdk.test.whitebox.WhiteBox + * @build compiler.calls.common.InvokeDynamic * @run driver compiler.calls.common.InvokeDynamicPatcher * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run main/othervm/native -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. diff --git a/test/hotspot/jtreg/compiler/jsr292/RedefineMethodUsedByMultipleMethodHandles.java b/test/hotspot/jtreg/compiler/jsr292/RedefineMethodUsedByMultipleMethodHandles.java index 769863880f2..9a74806e621 100644 --- a/test/hotspot/jtreg/compiler/jsr292/RedefineMethodUsedByMultipleMethodHandles.java +++ b/test/hotspot/jtreg/compiler/jsr292/RedefineMethodUsedByMultipleMethodHandles.java @@ -21,12 +21,11 @@ * questions. */ -/** +/* * @test * @bug 8042235 * @summary redefining method used by multiple MethodHandles crashes VM * @library / - * @library /testlibrary/asm * @modules java.compiler * java.instrument * jdk.attach @@ -37,15 +36,13 @@ package compiler.jsr292; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; - import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.lang.classfile.ClassFile; +import java.lang.classfile.ClassHierarchyResolver; +import java.lang.classfile.ClassTransform; +import java.lang.classfile.instruction.ConstantInstruction; import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.IllegalClassFormatException; import java.lang.instrument.Instrumentation; @@ -159,28 +156,15 @@ public class RedefineMethodUsedByMultipleMethodHandles { public byte[] transform(ClassLoader cl, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { if (Foo.class.equals(classBeingRedefined)) { System.out.println("redefining " + classBeingRedefined); - ClassReader cr = new ClassReader(classfileBuffer); - ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_FRAMES); - ClassVisitor adapter = new ClassVisitor(Opcodes.ASM5, cw) { - @Override - public MethodVisitor visitMethod(int access, String base, String desc, String signature, String[] exceptions) { - MethodVisitor mv = cv.visitMethod(access, base, desc, signature, exceptions); - if (mv != null) { - mv = new MethodVisitor(Opcodes.ASM5, mv) { - @Override - public void visitLdcInsn(Object cst) { - System.out.println("replacing \"" + cst + "\" with \"bar\""); - mv.visitLdcInsn("bar"); - } - }; - } - return mv; + var context = ClassFile.of(ClassFile.ClassHierarchyResolverOption.of(ClassHierarchyResolver.ofResourceParsing(cl))); + return context.transformClass(context.parse(classfileBuffer), ClassTransform.transformingMethodBodies((codeBuilder, codeElement) -> { + if (codeElement instanceof ConstantInstruction.LoadConstantInstruction ldc) { + System.out.println("replacing \"" + ldc.constantEntry().constantValue() + "\" with \"bar\""); + codeBuilder.ldc("bar"); + } else { + codeBuilder.with(codeElement); } - }; - - cr.accept(adapter, ClassReader.SKIP_FRAMES); - cw.visitEnd(); - return cw.toByteArray(); + })); } return classfileBuffer; } diff --git a/test/hotspot/jtreg/compiler/jvmci/common/CTVMUtilities.java b/test/hotspot/jtreg/compiler/jvmci/common/CTVMUtilities.java index 95917f6d943..c98d9944c80 100644 --- a/test/hotspot/jtreg/compiler/jvmci/common/CTVMUtilities.java +++ b/test/hotspot/jtreg/compiler/jvmci/common/CTVMUtilities.java @@ -23,28 +23,26 @@ package compiler.jvmci.common; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.Label; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.tree.ClassNode; -import jdk.test.lib.Utils; import jdk.vm.ci.code.InstalledCode; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.hotspot.CompilerToVMHelper; -import jdk.vm.ci.hotspot.HotSpotNmethod; import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod; import java.io.IOException; +import java.lang.classfile.Attributes; +import java.lang.classfile.ClassFile; +import java.lang.classfile.ClassModel; +import java.lang.classfile.MethodModel; +import java.lang.constant.ClassDesc; +import java.lang.constant.ConstantDescs; +import java.lang.constant.MethodTypeDesc; +import java.lang.invoke.MethodType; import java.lang.reflect.Constructor; import java.lang.reflect.Executable; -import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.lang.reflect.Parameter; -import java.util.HashMap; +import java.util.Arrays; +import java.util.List; import java.util.Map; import java.util.TreeMap; @@ -71,76 +69,55 @@ public class CTVMUtilities { } public static Map getBciToLineNumber(Executable method) { - Map lineNumbers = new TreeMap<>(); - Class aClass = method.getDeclaringClass(); - ClassReader cr; - try { - Module aModule = aClass.getModule(); - String name = aClass.getName(); - cr = new ClassReader(aModule.getResourceAsStream( - name.replace('.', '/') + ".class")); - } catch (IOException e) { - throw new Error("TEST BUG: can read " + aClass.getName() + " : " + e, e); - } - ClassNode cn = new ClassNode(); - cr.accept(cn, ClassReader.EXPAND_FRAMES); + ClassModel classModel = findClassBytes(method.getDeclaringClass()); + MethodModel methodModel = findMethod(classModel, method); + if (methodModel == null) + return Map.of(); - Map labels = new HashMap<>(); - ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES); - ClassVisitor cv = new ClassVisitorForLabels(cw, labels, method); - cr.accept(cv, ClassReader.EXPAND_FRAMES); - labels.forEach((k, v) -> lineNumbers.put(k.getOffset(), v)); - boolean isEmptyMethod = Modifier.isAbstract(method.getModifiers()) - || Modifier.isNative(method.getModifiers()); - if (lineNumbers.isEmpty() && !isEmptyMethod) { - throw new Error(method + " doesn't contains the line numbers table " - +"(the method marked neither abstract nor native)"); + var foundLineNumberTable = methodModel.code().flatMap(code -> + code.findAttribute(Attributes.lineNumberTable())); + if (foundLineNumberTable.isEmpty()) { + boolean isEmptyMethod = Modifier.isAbstract(method.getModifiers()) + || Modifier.isNative(method.getModifiers()); + if (!isEmptyMethod) { + throw new Error(method + " doesn't contains the line numbers table " + + "(the method marked neither abstract nor native)"); + } + return Map.of(); } + + Map lineNumbers = new TreeMap<>(); + foundLineNumberTable.get().lineNumbers().forEach(ln -> + lineNumbers.put(ln.startPc(), ln.lineNumber())); return lineNumbers; } - private static class ClassVisitorForLabels extends ClassVisitor { - private final Map lineNumbers; - private final String targetName; - private final String targetDesc; - - public ClassVisitorForLabels(ClassWriter cw, Map lines, - Executable target) { - super(Opcodes.ASM7, cw); - this.lineNumbers = lines; - - StringBuilder builder = new StringBuilder("("); - for (Parameter parameter : target.getParameters()) { - builder.append(Utils.toJVMTypeSignature(parameter.getType())); - } - builder.append(")"); - if (target instanceof Constructor) { - targetName = ""; - builder.append("V"); - } else { - targetName = target.getName(); - builder.append(Utils.toJVMTypeSignature( - ((Method) target).getReturnType())); - } - targetDesc = builder.toString(); + // Finds the ClassFile API model of a given class, or fail with an Error. + public static ClassModel findClassBytes(Class clazz) { + String binaryName = clazz.getName(); + byte[] fileBytes; + try (var inputStream = clazz.getModule().getResourceAsStream( + binaryName.replace('.', '/') + ".class")) { + fileBytes = inputStream.readAllBytes(); + } catch (IOException e) { + throw new Error("TEST BUG: cannot read " + binaryName, e); } + return ClassFile.of().parse(fileBytes); + } - @Override - public final MethodVisitor visitMethod(int access, String name, - String desc, String signature, - String[] exceptions) { - MethodVisitor mv = cv.visitMethod(access, name, desc, signature, - exceptions); - if (targetDesc.equals(desc) && targetName.equals(name)) { - return new MethodVisitor(Opcodes.ASM7, mv) { - @Override - public void visitLineNumber(int i, Label label) { - super.visitLineNumber(i, label); - lineNumbers.put(label, i); - } - }; + // Finds a matching method in a class model, or null if none match. + public static MethodModel findMethod(ClassModel classModel, Executable method) { + MethodTypeDesc methodType = MethodType.methodType( + method instanceof Method m ? m.getReturnType() : void.class, + method.getParameterTypes()).describeConstable().orElseThrow(); + String methodName = method instanceof Method m ? m.getName() : ConstantDescs.INIT_NAME; + + for (var methodModel : classModel.methods()) { + if (methodModel.methodName().equalsString(methodName) + && methodModel.methodType().isMethodType(methodType)) { + return methodModel; } - return mv; } + return null; } } diff --git a/test/hotspot/jtreg/runtime/MirrorFrame/Asmator.java b/test/hotspot/jtreg/runtime/MirrorFrame/Asmator.java index c5d9a4cb595..d8165d80196 100644 --- a/test/hotspot/jtreg/runtime/MirrorFrame/Asmator.java +++ b/test/hotspot/jtreg/runtime/MirrorFrame/Asmator.java @@ -21,35 +21,28 @@ * questions. */ -import org.objectweb.asm.*; +import java.lang.classfile.ClassFile; +import java.lang.classfile.ClassTransform; +import java.lang.classfile.CodeBuilder; +import java.lang.classfile.CodeElement; +import java.lang.classfile.CodeTransform; class Asmator { - static byte[] fixup(byte[] buf) throws java.io.IOException { - ClassReader cr = new ClassReader(buf); - ClassWriter cw = new ClassWriter(0); - ClassVisitor cv = new ClassVisitor(Opcodes.ASM4, cw) { - public MethodVisitor visitMethod( - final int access, - final String name, - final String desc, - final String signature, - final String[] exceptions) - { - MethodVisitor mv = super.visitMethod(access, - name, - desc, - signature, - exceptions); - if (mv == null) return null; - if (name.equals("callme")) { - // make receiver go dead! - mv.visitInsn(Opcodes.ACONST_NULL); - mv.visitVarInsn(Opcodes.ASTORE, 0); + static byte[] fixup(byte[] buf) { + return ClassFile.of().transformClass(ClassFile.of().parse(buf), ClassTransform.transformingMethodBodies( + m -> m.methodName().equalsString("callme"), + new CodeTransform() { + @Override + public void atStart(CodeBuilder builder) { + // make receiver go dead! + builder.aconst_null().astore(0); + } + + @Override + public void accept(CodeBuilder builder, CodeElement element) { + builder.with(element); // pass through + } } - return mv; - } - }; - cr.accept(cv, 0); - return cw.toByteArray(); + )); } } diff --git a/test/hotspot/jtreg/runtime/MirrorFrame/Test8003720.java b/test/hotspot/jtreg/runtime/MirrorFrame/Test8003720.java index 43c8fefacd2..5bcae8e45d1 100644 --- a/test/hotspot/jtreg/runtime/MirrorFrame/Test8003720.java +++ b/test/hotspot/jtreg/runtime/MirrorFrame/Test8003720.java @@ -25,7 +25,6 @@ * @test * @bug 8003720 * @summary Method in interpreter stack frame can be deallocated - * @library /testlibrary/asm * @modules java.base/jdk.internal.misc * @compile -XDignore.symbol.file Victim.java * @run main/othervm -Xverify:all -Xint Test8003720 diff --git a/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/MissedStackMapFrames/MissedStackMapFrames.java b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/MissedStackMapFrames/MissedStackMapFrames.java index 534f077eaf4..941c6e79bb8 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/MissedStackMapFrames/MissedStackMapFrames.java +++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/MissedStackMapFrames/MissedStackMapFrames.java @@ -27,17 +27,15 @@ * @bug 8228604 * * @requires vm.jvmti - * @library /testlibrary/asm * @library /test/lib * * @run main/othervm/native -agentlib:MissedStackMapFrames MissedStackMapFrames */ -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; - +import java.lang.classfile.Attributes; +import java.lang.classfile.ClassFile; +import java.lang.classfile.ClassModel; +import java.lang.classfile.MethodModel; public class MissedStackMapFrames { static { @@ -58,30 +56,19 @@ public class MissedStackMapFrames { private static native byte[] retransformBytes(int idx); private static int getStackMapFrameCount(byte[] classfileBuffer) { - ClassReader reader = new ClassReader(classfileBuffer); - final int[] frameCount = {0}; - ClassVisitor cv = new ClassVisitor(Opcodes.ASM9) { - @Override - public MethodVisitor visitMethod(int access, String name, - String descriptor, String signature, - String[] exceptions) { - return new MethodVisitor(Opcodes.ASM9) { - private int methodFrames = 0; - @Override - public void visitFrame(int type, int numLocal, Object[] local, - int numStack, Object[] stack) { - methodFrames++; - } - @Override - public void visitEnd() { - log(" method " + name + " - " + methodFrames + " frames"); - frameCount[0] += methodFrames; - } - }; + ClassModel clazz = ClassFile.of().parse(classfileBuffer); + int count = 0; + for (MethodModel method : clazz.methods()) { + var foundStackMapTable = method.code().flatMap(code -> code.findAttribute(Attributes.stackMapTable())); + if (foundStackMapTable.isPresent()) { + int methodFrames = foundStackMapTable.get().entries().size(); + log(" method " + method.methodName() + " - " + methodFrames + " frames"); + count += methodFrames; + } else { + log(" method " + method.methodName() + " - No StackMapTable"); } - }; - reader.accept(cv, 0); - return frameCount[0]; + } + return count; } private static int checkStackMapFrames(String mode, byte[] classfileBuffer) { diff --git a/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineAnnotations.java b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineAnnotations.java index aad876d7181..320531148d4 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineAnnotations.java +++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineAnnotations.java @@ -24,7 +24,6 @@ /* * @test * @library /test/lib - * @library /testlibrary/asm * @summary Test that type annotations are retained after a retransform * @requires vm.jvmti * @modules java.base/jdk.internal.misc @@ -46,6 +45,11 @@ import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import java.lang.classfile.ClassBuilder; +import java.lang.classfile.ClassElement; +import java.lang.classfile.ClassFile; +import java.lang.classfile.ClassTransform; +import java.lang.classfile.FieldModel; import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.IllegalClassFormatException; import java.lang.instrument.Instrumentation; @@ -55,17 +59,10 @@ import java.lang.reflect.AnnotatedParameterizedType; import java.lang.reflect.AnnotatedType; import java.lang.reflect.AnnotatedWildcardType; import java.lang.reflect.Executable; -import java.lang.reflect.TypeVariable; import java.security.ProtectionDomain; -import java.util.Arrays; -import java.util.LinkedList; +import java.util.ArrayList; import java.util.List; import java.util.Map; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.FieldVisitor; -import static org.objectweb.asm.Opcodes.ASM7; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE_USE) @@ -86,53 +83,27 @@ public class RedefineAnnotations { ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { - ClassWriter cw = new ClassWriter(0); - ClassVisitor cv = new ReAddDummyFieldsClassVisitor(ASM7, cw) { }; - ClassReader cr = new ClassReader(classfileBuffer); - cr.accept(cv, 0); - return cw.toByteArray(); - } + // Shuffle constant pool + ClassFile context = ClassFile.of(ClassFile.ConstantPoolSharingOption.NEW_POOL); + return context.transformClass(context.parse(classfileBuffer), new ClassTransform() { + final List dummyFields = new ArrayList<>(); - public class ReAddDummyFieldsClassVisitor extends ClassVisitor { - - LinkedList fields = new LinkedList<>(); - - public ReAddDummyFieldsClassVisitor(int api, ClassVisitor cv) { - super(api, cv); - } - - @Override public FieldVisitor visitField(int access, String name, - String desc, String signature, Object value) { - if (name.startsWith("dummy")) { - // Remove dummy field - fields.addLast(new F(access, name, desc, signature, value)); - return null; + @Override + public void accept(ClassBuilder builder, ClassElement element) { + if (element instanceof FieldModel field && field.fieldName().stringValue().startsWith("dummy")) { + // Hold on to the associated constant pool entries too + dummyFields.addLast(field); + } else { + builder.with(element); + } } - return cv.visitField(access, name, desc, signature, value); - } - @Override public void visitEnd() { - F f; - while ((f = fields.pollFirst()) != null) { - // Re-add dummy fields - cv.visitField(f.access, f.name, f.desc, f.signature, f.value); + @Override + public void atEnd(ClassBuilder builder) { + // Add the associated constant pool entries to the end of the CP + dummyFields.forEach(builder); } - } - - private class F { - private int access; - private String name; - private String desc; - private String signature; - private Object value; - F(int access, String name, String desc, String signature, Object value) { - this.access = access; - this.name = name; - this.desc = desc; - this.signature = signature; - this.value = value; - } - } + }); } @Override public byte[] transform(ClassLoader loader, String className, diff --git a/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineGenericSignatureTest.java b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineGenericSignatureTest.java index f220a93f187..923253e8051 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineGenericSignatureTest.java +++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineGenericSignatureTest.java @@ -35,6 +35,11 @@ import java.io.File; import java.io.FileOutputStream; +import java.lang.classfile.ClassBuilder; +import java.lang.classfile.ClassElement; +import java.lang.classfile.ClassFile; +import java.lang.classfile.ClassTransform; +import java.lang.classfile.attribute.SourceFileAttribute; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; @@ -141,27 +146,28 @@ public class RedefineGenericSignatureTest { private byte[] getNewClassBytes() { byte[] bytecode = InMemoryJavaCompiler.compile(GenericSignatureTarget.class.getName(), newTargetClassSource); - ClassWriter cw = new ClassWriter(0); - ClassReader cr = new ClassReader(bytecode); - cr.accept(new ClassVisitor(Opcodes.ASM7, cw) { + ClassFile context = ClassFile.of(); + return context.transformClass(context.parse(bytecode), new ClassTransform() { private boolean sourceSet = false; @Override - public void visitSource(String source, String debug) { - sourceSet = true; - log("Changing source: \"" + source + "\" -> \"" + sourceFileNameNew + "\""); - super.visitSource(sourceFileNameNew, debug); + public void accept(ClassBuilder builder, ClassElement element) { + if (element instanceof SourceFileAttribute src) { + sourceSet = true; + log("Changing source: \"" + src.sourceFile() + "\" -> \"" + sourceFileNameNew + "\""); + builder.with(SourceFileAttribute.of(sourceFileNameNew)); + } else { + builder.with(element); + } } @Override - public void visitEnd() { + public void atEnd(ClassBuilder builder) { if (!sourceSet) { log("Set source: \"" + sourceFileNameNew + "\""); - super.visitSource(sourceFileNameNew, null); + builder.with(SourceFileAttribute.of(sourceFileNameNew)); } - super.visitEnd(); } - }, 0); - return cw.toByteArray(); + }); } private void runTest() throws Throwable { diff --git a/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineObject.java b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineObject.java index de90c15b5a5..d3349282410 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineObject.java +++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineObject.java @@ -27,7 +27,6 @@ * @summary Ensure Object natives stay registered after redefinition * @requires vm.jvmti * @library /test/lib - * @library /testlibrary/asm * @modules java.base/jdk.internal.misc * java.compiler * java.instrument @@ -41,19 +40,15 @@ import jdk.test.lib.helpers.ClassFileInstaller; import java.io.FileNotFoundException; import java.io.PrintWriter; import java.lang.RuntimeException; +import java.lang.classfile.ClassBuilder; +import java.lang.classfile.ClassElement; +import java.lang.classfile.ClassFile; +import java.lang.classfile.ClassFileVersion; import java.lang.instrument.ClassFileTransformer; import java.lang.instrument.IllegalClassFormatException; import java.lang.instrument.Instrumentation; import java.lang.instrument.UnmodifiableClassException; import java.security.ProtectionDomain; -import java.util.Arrays; - -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.ClassWriter; - -import static org.objectweb.asm.Opcodes.ASM6; -import static org.objectweb.asm.Opcodes.V1_8; public class RedefineObject { @@ -69,31 +64,14 @@ public class RedefineObject { Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException { - ClassWriter cw = new ClassWriter(0); - // Force an older ASM to force a bytecode update - ClassVisitor cv = new DummyClassVisitor(ASM6, cw) { }; - ClassReader cr = new ClassReader(classfileBuffer); - cr.accept(cv, 0); - byte[] bytes = cw.toByteArray(); - return bytes; - } - - public class DummyClassVisitor extends ClassVisitor { - - public DummyClassVisitor(int api, ClassVisitor cv) { - super(api, cv); - } - - public void visit( - final int version, - final int access, - final String name, - final String signature, - final String superName, - final String[] interfaces) { - // Artificially lower to JDK 8 version to force a redefine - cv.visit(V1_8, access, name, signature, superName, interfaces); - } + return ClassFile.of().transformClass(ClassFile.of().parse(classfileBuffer), (classBuilder, classElement) -> { + if (classElement instanceof ClassFileVersion cfv) { + // Force a redefine with different class file versions + classBuilder.with(ClassFileVersion.of(cfv.majorVersion() - 1, 0)); + } else { + classBuilder.with(classElement); + } + }); } @Override public byte[] transform(ClassLoader loader, String className, diff --git a/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineRetransform/RedefineRetransform.java b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineRetransform/RedefineRetransform.java index a09d1dc318e..167b546ac9d 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineRetransform/RedefineRetransform.java +++ b/test/hotspot/jtreg/serviceability/jvmti/RedefineClasses/RedefineRetransform/RedefineRetransform.java @@ -27,7 +27,6 @@ * @bug 7124710 * * @requires vm.jvmti - * @library /testlibrary/asm * @library /test/lib * * @comment main/othervm/native -Xlog:redefine*=trace -agentlib:RedefineRetransform RedefineRetransform @@ -42,13 +41,17 @@ import java.io.IOException; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; - -import org.objectweb.asm.AnnotationVisitor; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; +import java.lang.classfile.Annotation; +import java.lang.classfile.AnnotationElement; +import java.lang.classfile.AnnotationValue; +import java.lang.classfile.Attributes; +import java.lang.classfile.ClassFile; +import java.lang.classfile.ClassModel; +import java.lang.classfile.ClassTransform; +import java.lang.classfile.attribute.RuntimeVisibleAnnotationsAttribute; +import java.lang.constant.ClassDesc; +import java.util.List; +import java.util.NoSuchElementException; /* * The test verifies that after interleaved RedefineClasses/RetransformClasses calls @@ -81,67 +84,32 @@ public class RedefineRetransform { // Class bytes for initial TestClass (ClassVersion == 0). private static byte[] initialClassBytes; - private static class VersionScanner extends ClassVisitor { - private Integer detectedVersion; - private Integer versionToSet; - // to get version - public VersionScanner() { - super(Opcodes.ASM7); - } - // to set version - public VersionScanner(int verToSet, ClassVisitor classVisitor) { - super(Opcodes.ASM7, classVisitor); - versionToSet = verToSet; - } - - public int detectedVersion() { - if (detectedVersion == null) { - throw new RuntimeException("Version not detected"); - } - return detectedVersion; - } - - @Override - public AnnotationVisitor visitAnnotation(String descriptor, boolean visible) { - //log("visitAnnotation: descr = '" + descriptor + "', visible = " + visible); - if (Type.getDescriptor(ClassVersion.class).equals(descriptor)) { - return new AnnotationVisitor(Opcodes.ASM7, super.visitAnnotation(descriptor, visible)) { - @Override - public void visit(String name, Object value) { - //log("visit: name = '" + name + "', value = " + value - // + " (" + (value == null ? "N/A" : value.getClass()) + ")"); - if ("value".equals(name) && value instanceof Integer intValue) { - detectedVersion = intValue; - if (versionToSet != null) { - //log("replace with " + versionToSet); - value = versionToSet; - } - } - super.visit(name, value); - } - }; - } - return super.visitAnnotation(descriptor, visible); - } - } + private static final ClassDesc CD_ClassVersion = ClassVersion.class.describeConstable().orElseThrow(); // Generates TestClass class bytes with the specified ClassVersion value. private static byte[] getClassBytes(int ver) { if (ver < 0) { return null; } - ClassWriter cw = new ClassWriter(0); - ClassReader cr = new ClassReader(initialClassBytes); - cr.accept(new VersionScanner(ver, cw), 0); - return cw.toByteArray(); + return ClassFile.of().transformClass(ClassFile.of().parse(initialClassBytes), + // overwrites previously passed RVAA + ClassTransform.endHandler(classBuilder -> classBuilder.with(RuntimeVisibleAnnotationsAttribute + .of(Annotation.of(CD_ClassVersion, AnnotationElement.ofInt("value", ver)))))); } // Extracts ClassVersion values from the provided class bytes. private static int getClassBytesVersion(byte[] classBytes) { - ClassReader cr = new ClassReader(classBytes); - VersionScanner scanner = new VersionScanner(); - cr.accept(scanner, 0); - return scanner.detectedVersion(); + ClassModel classModel = ClassFile.of().parse(classBytes); + RuntimeVisibleAnnotationsAttribute rvaa = classModel.findAttribute(Attributes.runtimeVisibleAnnotations()).orElseThrow(); + List classVersionElementValuePairs = rvaa.annotations().stream() + .filter(anno -> anno.className().isFieldType(CD_ClassVersion)) + .findFirst().orElseThrow().elements(); + if (classVersionElementValuePairs.size() != 1) + throw new NoSuchElementException(); + AnnotationElement elementValuePair = classVersionElementValuePairs.getFirst(); + if (!elementValuePair.name().equalsString("value") || !(elementValuePair.value() instanceof AnnotationValue.OfInt intVal)) + throw new NoSuchElementException(); + return intVal.intValue(); } static void init() { diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/GenClassPoolJar.java b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/GenClassPoolJar.java index cea00fc2efc..511db8b8ed1 100644 --- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/GenClassPoolJar.java +++ b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/GenClassPoolJar.java @@ -26,6 +26,9 @@ package gc.g1.unloading; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import java.lang.classfile.ClassFile; +import java.lang.classfile.ClassTransform; +import java.lang.constant.ClassDesc; import java.nio.file.FileVisitResult; import java.nio.file.FileVisitor; import java.nio.file.Files; @@ -42,11 +45,6 @@ import javax.tools.JavaCompiler; import javax.tools.JavaFileObject; import javax.tools.StandardJavaFileManager; import javax.tools.ToolProvider; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.Opcodes; - /** * Class that imitates shell script to produce jar file with many similar * classes inside. @@ -261,28 +259,9 @@ public class GenClassPoolJar { * @return new class file to write into class */ byte[] morphClass(byte[] classToMorph, String newName) { - ClassReader cr = new ClassReader(classToMorph); - ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS); - ClassVisitor cv = new ClassRenamer(cw, newName); - cr.accept(cv, 0); - return cw.toByteArray(); + var context = ClassFile.of(); + return context.transformClass(context.parse(classToMorph), + ClassDesc.ofInternalName(newName), + ClassTransform.ACCEPT_ALL); } - - /** - * Visitor to rename class. - */ - static class ClassRenamer extends ClassVisitor implements Opcodes { - private final String newName; - - public ClassRenamer(ClassVisitor cv, String newName) { - super(ASM4, cv); - this.newName = newName; - } - - @Override - public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { - cv.visit(version, access, newName, signature, superName, interfaces); - } - - } } diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_inMemoryCompilation_keep_cl/TestDescription.java b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_inMemoryCompilation_keep_cl/TestDescription.java index 19b2a940788..5337aa73d2e 100644 --- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_inMemoryCompilation_keep_cl/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_inMemoryCompilation_keep_cl/TestDescription.java @@ -30,7 +30,6 @@ * VM Testbase keywords: [gc, stress, stressopt, nonconcurrent, javac] * * @modules java.base/jdk.internal.misc - * @library /testlibrary/asm * @library /vmTestbase * /test/lib * diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_inMemoryCompilation_keep_class/TestDescription.java b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_inMemoryCompilation_keep_class/TestDescription.java index b84411234a5..75d45dda2fe 100644 --- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_inMemoryCompilation_keep_class/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_inMemoryCompilation_keep_class/TestDescription.java @@ -30,7 +30,6 @@ * VM Testbase keywords: [gc, stress, stressopt, nonconcurrent, javac] * * @modules java.base/jdk.internal.misc - * @library /testlibrary/asm * @library /vmTestbase * /test/lib * diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_inMemoryCompilation_keep_obj/TestDescription.java b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_inMemoryCompilation_keep_obj/TestDescription.java index f0cc45744c4..aceade65a66 100644 --- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_inMemoryCompilation_keep_obj/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_inMemoryCompilation_keep_obj/TestDescription.java @@ -30,7 +30,6 @@ * VM Testbase keywords: [gc, stress, stressopt, nonconcurrent, javac] * * @modules java.base/jdk.internal.misc - * @library /testlibrary/asm * @library /vmTestbase * /test/lib * diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_keep_cl/TestDescription.java b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_keep_cl/TestDescription.java index 48f1680897f..a2547a7556f 100644 --- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_keep_cl/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_keep_cl/TestDescription.java @@ -30,7 +30,6 @@ * VM Testbase keywords: [gc, stress, stressopt, nonconcurrent, javac] * * @modules java.base/jdk.internal.misc - * @library /testlibrary/asm * @library /vmTestbase * /test/lib * diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_keep_class/TestDescription.java b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_keep_class/TestDescription.java index 68263db73ac..d822f65034d 100644 --- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_keep_class/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_keep_class/TestDescription.java @@ -30,7 +30,6 @@ * VM Testbase keywords: [gc, stress, stressopt, nonconcurrent, javac] * * @modules java.base/jdk.internal.misc - * @library /testlibrary/asm * @library /vmTestbase * /test/lib * diff --git a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_keep_obj/TestDescription.java b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_keep_obj/TestDescription.java index 4ee02a649d3..e875b964f0f 100644 --- a/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_keep_obj/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/gc/g1/unloading/tests/unloading_keepRef_rootClass_keep_obj/TestDescription.java @@ -30,7 +30,6 @@ * VM Testbase keywords: [gc, stress, stressopt, nonconcurrent, javac] * * @modules java.base/jdk.internal.misc - * @library /testlibrary/asm * @library /vmTestbase * /test/lib * diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetClassFields/getclfld007.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetClassFields/getclfld007.java index 6d79e479b97..300966c04dd 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetClassFields/getclfld007.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetClassFields/getclfld007.java @@ -25,14 +25,12 @@ package nsk.jvmti.GetClassFields; import java.io.PrintStream; import java.io.InputStream; +import java.lang.classfile.ClassFile; +import java.lang.classfile.ClassModel; +import java.lang.classfile.FieldModel; import java.util.List; import java.util.ArrayList; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.FieldVisitor; -import org.objectweb.asm.Opcodes; - public class getclfld007 { @@ -79,44 +77,29 @@ public class getclfld007 { static void check(Class cls) throws Exception { - FieldExplorer explorer = new FieldExplorer(cls); - List fields = explorer.get(); + List fields = getFields(cls); check(cls, fields.toArray(new String[0])); } - // helper class to get list of the class fields - // in the order they appear in the class file - static class FieldExplorer extends ClassVisitor { - private final Class cls; - private List fieldNameAndSig = new ArrayList<>(); - private FieldExplorer(Class cls) { - super(Opcodes.ASM7); - this.cls = cls; - } + private static InputStream getClassBytes(Class cls) throws Exception { + String clsName = cls.getName(); + String clsPath = clsName.replace('.', '/') + ".class"; + return cls.getClassLoader().getResourceAsStream(clsPath); + } - @Override - public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) { - System.out.println(" field '" + name + "', type = " + descriptor); - fieldNameAndSig.add(name); - fieldNameAndSig.add(descriptor); - return super.visitField(access, name, descriptor, signature, value); - } - - private InputStream getClassBytes() throws Exception { - String clsName = cls.getName(); - String clsPath = clsName.replace('.', '/') + ".class"; - return cls.getClassLoader().getResourceAsStream(clsPath); - } - - // each field is represented by 2 Strings in the list: name and type descriptor - public List get() throws Exception { - System.out.println("Class " + cls.getName()); - try (InputStream classBytes = getClassBytes()) { - ClassReader classReader = new ClassReader(classBytes); - classReader.accept(this, 0); + // get list of the class fields in the order they appear in the class file + // each field is represented by 2 Strings in the list: name and type descriptor + public static List getFields(Class cls) throws Exception { + System.out.println("Class " + cls.getName()); + List fieldNameAndSig = new ArrayList<>(); + try (InputStream classBytes = getClassBytes(cls)) { + ClassModel classModel = ClassFile.of().parse(classBytes.readAllBytes()); + for (FieldModel field : classModel.fields()) { + fieldNameAndSig.add(field.fieldName().stringValue()); + fieldNameAndSig.add(field.fieldType().stringValue()); } - return fieldNameAndSig; } + return fieldNameAndSig; } static class InnerClass1 { From 1392a0b4608f6196f207fcebbab75b2d79fdc758 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Thu, 16 Oct 2025 19:55:07 +0000 Subject: [PATCH 0250/1639] 8368740: Serial: Swap eden and survivor spaces position in young generation Reviewed-by: gli, fandreuzzi --- .../share/gc/serial/defNewGeneration.cpp | 271 +++++++++--------- .../share/gc/serial/defNewGeneration.hpp | 24 +- src/hotspot/share/gc/serial/serialHeap.cpp | 9 +- src/hotspot/share/gc/serial/serialHeap.hpp | 8 +- src/hotspot/share/gc/shared/space.cpp | 5 +- 5 files changed, 165 insertions(+), 152 deletions(-) diff --git a/src/hotspot/share/gc/serial/defNewGeneration.cpp b/src/hotspot/share/gc/serial/defNewGeneration.cpp index 5b7bc744236..aef896182c0 100644 --- a/src/hotspot/share/gc/serial/defNewGeneration.cpp +++ b/src/hotspot/share/gc/serial/defNewGeneration.cpp @@ -225,16 +225,12 @@ DefNewGeneration::DefNewGeneration(ReservedSpace rs, _promo_failure_drain_in_progress(false), _string_dedup_requests() { - MemRegion cmr((HeapWord*)_virtual_space.low(), - (HeapWord*)_virtual_space.high()); - SerialHeap* gch = SerialHeap::heap(); - - gch->rem_set()->resize_covered_region(cmr); - _eden_space = new ContiguousSpace(); _from_space = new ContiguousSpace(); _to_space = new ContiguousSpace(); + init_spaces(); + // Compute the maximum eden and survivor space sizes. These sizes // are computed assuming the entire reserved space is committed. // These values are exported as performance counters. @@ -256,7 +252,6 @@ DefNewGeneration::DefNewGeneration(ReservedSpace rs, _to_counters = new CSpaceCounters("s1", 2, _max_survivor_size, _to_space, _gen_counters); - compute_space_boundaries(0, SpaceDecorator::Clear, SpaceDecorator::Mangle); update_counters(); _old_gen = nullptr; _tenuring_threshold = MaxTenuringThreshold; @@ -268,74 +263,51 @@ DefNewGeneration::DefNewGeneration(ReservedSpace rs, _gc_tracer = new DefNewTracer(); } -void DefNewGeneration::compute_space_boundaries(uintx minimum_eden_size, - bool clear_space, - bool mangle_space) { - // If the spaces are being cleared (only done at heap initialization - // currently), the survivor spaces need not be empty. - // Otherwise, no care is taken for used areas in the survivor spaces - // so check. - assert(clear_space || (to()->is_empty() && from()->is_empty()), - "Initialization of the survivor spaces assumes these are empty"); +void DefNewGeneration::init_spaces() { + // Using layout: from, to, eden, so only from can be non-empty. + assert(eden()->is_empty(), "precondition"); + assert(to()->is_empty(), "precondition"); + + if (!from()->is_empty()) { + assert((char*) from()->bottom() == _virtual_space.low(), "inv"); + } // Compute sizes - uintx size = _virtual_space.committed_size(); - uintx survivor_size = compute_survivor_size(size, SpaceAlignment); - uintx eden_size = size - (2*survivor_size); - if (eden_size > max_eden_size()) { - // Need to reduce eden_size to satisfy the max constraint. The delta needs - // to be 2*SpaceAlignment aligned so that both survivors are properly - // aligned. - uintx eden_delta = align_up(eden_size - max_eden_size(), 2*SpaceAlignment); - eden_size -= eden_delta; - survivor_size += eden_delta/2; - } + size_t size = _virtual_space.committed_size(); + size_t survivor_size = compute_survivor_size(size, SpaceAlignment); + assert(survivor_size >= from()->used(), "inv"); + assert(size > 2 * survivor_size, "inv"); + size_t eden_size = size - (2 * survivor_size); assert(eden_size > 0 && survivor_size <= eden_size, "just checking"); - if (eden_size < minimum_eden_size) { - // May happen due to 64Kb rounding, if so adjust eden size back up - minimum_eden_size = align_up(minimum_eden_size, SpaceAlignment); - uintx maximum_survivor_size = (size - minimum_eden_size) / 2; - uintx unaligned_survivor_size = - align_down(maximum_survivor_size, SpaceAlignment); - survivor_size = MAX2(unaligned_survivor_size, SpaceAlignment); - eden_size = size - (2*survivor_size); - assert(eden_size > 0 && survivor_size <= eden_size, "just checking"); - assert(eden_size >= minimum_eden_size, "just checking"); - } + // layout: from, to, eden + char* from_start = _virtual_space.low(); + char* to_start = from_start + survivor_size; + char* eden_start = to_start + survivor_size; + char* eden_end = eden_start + eden_size; - char *eden_start = _virtual_space.low(); - char *from_start = eden_start + eden_size; - char *to_start = from_start + survivor_size; - char *to_end = to_start + survivor_size; - - assert(to_end == _virtual_space.high(), "just checking"); - assert(is_aligned(eden_start, SpaceAlignment), "checking alignment"); + assert(eden_end == _virtual_space.high(), "just checking"); assert(is_aligned(from_start, SpaceAlignment), "checking alignment"); assert(is_aligned(to_start, SpaceAlignment), "checking alignment"); + assert(is_aligned(eden_start, SpaceAlignment), "checking alignment"); + assert(is_aligned(eden_end, SpaceAlignment), "checking alignment"); - MemRegion edenMR((HeapWord*)eden_start, (HeapWord*)from_start); MemRegion fromMR((HeapWord*)from_start, (HeapWord*)to_start); - MemRegion toMR ((HeapWord*)to_start, (HeapWord*)to_end); - - // A minimum eden size implies that there is a part of eden that - // is being used and that affects the initialization of any - // newly formed eden. - bool live_in_eden = minimum_eden_size > 0; + MemRegion toMR ((HeapWord*)to_start, (HeapWord*)eden_start); + MemRegion edenMR((HeapWord*)eden_start, (HeapWord*)eden_end); // Reset the spaces for their new regions. - eden()->initialize(edenMR, - clear_space && !live_in_eden, - SpaceDecorator::Mangle); - // If clear_space and live_in_eden, we will not have cleared any - // portion of eden above its top. This can cause newly - // expanded space not to be mangled if using ZapUnusedHeapArea. - // We explicitly do such mangling here. - if (ZapUnusedHeapArea && clear_space && live_in_eden && mangle_space) { - eden()->mangle_unused_area(); - } - from()->initialize(fromMR, clear_space, mangle_space); - to()->initialize(toMR, clear_space, mangle_space); + from()->initialize(fromMR, from()->is_empty(), SpaceDecorator::Mangle); + to()->initialize(toMR, true, SpaceDecorator::Mangle); + eden()->initialize(edenMR, true, SpaceDecorator::Mangle); + + post_resize(); +} + +void DefNewGeneration::post_resize() { + MemRegion cmr((HeapWord*)_virtual_space.low(), + (HeapWord*)_virtual_space.high()); + SerialHeap::heap()->rem_set()->resize_covered_region(cmr); } void DefNewGeneration::swap_spaces() { @@ -351,20 +323,28 @@ void DefNewGeneration::swap_spaces() { } bool DefNewGeneration::expand(size_t bytes) { - HeapWord* prev_high = (HeapWord*) _virtual_space.high(); + assert(bytes != 0, "precondition"); + assert(is_aligned(bytes, SpaceAlignment), "precondition"); + bool success = _virtual_space.expand_by(bytes); - if (success && ZapUnusedHeapArea) { - // Mangle newly committed space immediately because it - // can be done here more simply that after the new - // spaces have been computed. - HeapWord* new_high = (HeapWord*) _virtual_space.high(); - MemRegion mangle_region(prev_high, new_high); - SpaceMangler::mangle_region(mangle_region); + if (!success) { + log_info(gc)("Failed to expand young-gen by %zu bytes", bytes); } return success; } +void DefNewGeneration::expand_eden_by(size_t delta_bytes) { + if (!expand(delta_bytes)) { + return; + } + + MemRegion eden_mr{eden()->bottom(), (HeapWord*)_virtual_space.high()}; + eden()->initialize(eden_mr, eden()->is_empty(), SpaceDecorator::Mangle); + + post_resize(); +} + size_t DefNewGeneration::calculate_thread_increase_size(int threads_count) const { size_t thread_increase_size = 0; // Check an overflow at 'threads_count * NewSizeThreadIncrease'. @@ -397,18 +377,8 @@ size_t DefNewGeneration::adjust_for_thread_increase(size_t new_size_candidate, return desired_new_size; } -void DefNewGeneration::compute_new_size() { - // This is called after a GC that includes the old generation, so from-space - // will normally be empty. - // Note that we check both spaces, since if scavenge failed they revert roles. - // If not we bail out (otherwise we would have to relocate the objects). - if (!from()->is_empty() || !to()->is_empty()) { - return; - } - - SerialHeap* gch = SerialHeap::heap(); - - size_t old_size = gch->old_gen()->capacity(); +size_t DefNewGeneration::calculate_desired_young_gen_bytes() const { + size_t old_size = SerialHeap::heap()->old_gen()->capacity(); size_t new_size_before = _virtual_space.committed_size(); size_t min_new_size = NewSize; size_t max_new_size = reserved().byte_size(); @@ -429,46 +399,82 @@ void DefNewGeneration::compute_new_size() { // Adjust new generation size desired_new_size = clamp(desired_new_size, min_new_size, max_new_size); - assert(desired_new_size <= max_new_size, "just checking"); + if (!from()->is_empty()) { + // Mininum constraint to hold all live objs inside from-space. + size_t min_survivor_size = align_up(from()->used(), alignment); - bool changed = false; - if (desired_new_size > new_size_before) { - size_t change = desired_new_size - new_size_before; - assert(change % alignment == 0, "just checking"); - if (expand(change)) { - changed = true; + // SurvivorRatio := eden_size / survivor_size + // young-gen-size = eden_size + 2 * survivor_size + // = SurvivorRatio * survivor_size + 2 * survivor_size + // = (SurvivorRatio + 2) * survivor_size + size_t min_young_gen_size = min_survivor_size * (SurvivorRatio + 2); + + desired_new_size = MAX2(min_young_gen_size, desired_new_size); + } + assert(is_aligned(desired_new_size, alignment), "postcondition"); + + return desired_new_size; +} + +void DefNewGeneration::resize_inner() { + assert(eden()->is_empty(), "precondition"); + assert(to()->is_empty(), "precondition"); + + size_t current_young_gen_size_bytes = _virtual_space.committed_size(); + size_t desired_young_gen_size_bytes = calculate_desired_young_gen_bytes(); + if (current_young_gen_size_bytes == desired_young_gen_size_bytes) { + return; + } + + // Commit/uncommit + if (desired_young_gen_size_bytes > current_young_gen_size_bytes) { + size_t delta_bytes = desired_young_gen_size_bytes - current_young_gen_size_bytes; + if (!expand(delta_bytes)) { + return; } - // If the heap failed to expand to the desired size, - // "changed" will be false. If the expansion failed - // (and at this point it was expected to succeed), - // ignore the failure (leaving "changed" as false). + } else { + size_t delta_bytes = current_young_gen_size_bytes - desired_young_gen_size_bytes; + _virtual_space.shrink_by(delta_bytes); } - if (desired_new_size < new_size_before && eden()->is_empty()) { - // bail out of shrinking if objects in eden - size_t change = new_size_before - desired_new_size; - assert(change % alignment == 0, "just checking"); - _virtual_space.shrink_by(change); - changed = true; - } - if (changed) { - // The spaces have already been mangled at this point but - // may not have been cleared (set top = bottom) and should be. - // Mangling was done when the heap was being expanded. - compute_space_boundaries(eden()->used(), - SpaceDecorator::Clear, - SpaceDecorator::DontMangle); - MemRegion cmr((HeapWord*)_virtual_space.low(), - (HeapWord*)_virtual_space.high()); - gch->rem_set()->resize_covered_region(cmr); - log_debug(gc, ergo, heap)( - "New generation size %zuK->%zuK [eden=%zuK,survivor=%zuK]", - new_size_before/K, _virtual_space.committed_size()/K, - eden()->capacity()/K, from()->capacity()/K); - log_trace(gc, ergo, heap)( - " [allowed %zuK extra for %d threads]", - thread_increase_size/K, threads_count); - } + assert(desired_young_gen_size_bytes == _virtual_space.committed_size(), "inv"); + + init_spaces(); + + log_debug(gc, ergo, heap)("New generation size %zuK->%zuK [eden=%zuK,survivor=%zuK]", + current_young_gen_size_bytes/K, _virtual_space.committed_size()/K, + eden()->capacity()/K, from()->capacity()/K); +} + +void DefNewGeneration::resize_after_young_gc() { + // Called only after successful young-gc. + assert(eden()->is_empty(), "precondition"); + assert(to()->is_empty(), "precondition"); + + if ((char*)to()->bottom() == _virtual_space.low()) { + // layout: to, from, eden; can't resize. + return; + } + + assert((char*)from()->bottom() == _virtual_space.low(), "inv"); + resize_inner(); +} + +void DefNewGeneration::resize_after_full_gc() { + if (eden()->is_empty() && from()->is_empty() && to()->is_empty()) { + resize_inner(); + return; + } + + // Usually the young-gen is empty after full-gc. + // This is the extreme case; expand young-gen to its max size. + if (_virtual_space.uncommitted_size() == 0) { + // Already at its max size. + return; + } + + // Keep from/to and expand eden. + expand_eden_by(_virtual_space.uncommitted_size()); } void DefNewGeneration::ref_processor_init() { @@ -483,13 +489,11 @@ size_t DefNewGeneration::capacity() const { + from()->capacity(); // to() is only used during scavenge } - size_t DefNewGeneration::used() const { return eden()->used() + from()->used(); // to() is only used during scavenge } - size_t DefNewGeneration::free() const { return eden()->free() + from()->free(); // to() is only used during scavenge @@ -497,7 +501,8 @@ size_t DefNewGeneration::free() const { size_t DefNewGeneration::max_capacity() const { const size_t reserved_bytes = reserved().byte_size(); - return reserved_bytes - compute_survivor_size(reserved_bytes, SpaceAlignment); + const size_t min_survivor_bytes = SpaceAlignment; + return reserved_bytes - min_survivor_bytes; } bool DefNewGeneration::is_in(const void* p) const { @@ -589,7 +594,6 @@ bool DefNewGeneration::collect(bool clear_all_soft_refs) { IsAliveClosure is_alive(this); age_table()->clear(); - to()->clear(SpaceDecorator::Mangle); YoungGenScanClosure young_gen_cl(this); OldGenScanClosure old_gen_cl(this); @@ -839,13 +843,18 @@ void DefNewGeneration::print_on(outputStream* st) const { to()->print_on(st, "to "); } -HeapWord* DefNewGeneration::allocate(size_t word_size) { - // This is the slow-path allocation for the DefNewGeneration. - // Most allocations are fast-path in compiled code. - // We try to allocate from the eden. If that works, we are happy. - // Note that since DefNewGeneration supports lock-free allocation, we - // have to use it here, as well. - HeapWord* result = eden()->par_allocate(word_size); +HeapWord* DefNewGeneration::expand_and_allocate(size_t word_size) { + assert(SafepointSynchronize::is_at_safepoint(), "precondition"); + assert(Thread::current()->is_VM_thread(), "precondition"); + + size_t eden_free_bytes = eden()->free(); + size_t requested_bytes = word_size * HeapWordSize; + if (eden_free_bytes < requested_bytes) { + size_t expand_bytes = requested_bytes - eden_free_bytes; + expand_eden_by(align_up(expand_bytes, SpaceAlignment)); + } + + HeapWord* result = eden()->allocate(word_size); return result; } diff --git a/src/hotspot/share/gc/serial/defNewGeneration.hpp b/src/hotspot/share/gc/serial/defNewGeneration.hpp index 32b6b32f42f..40d2116cb58 100644 --- a/src/hotspot/share/gc/serial/defNewGeneration.hpp +++ b/src/hotspot/share/gc/serial/defNewGeneration.hpp @@ -131,6 +131,13 @@ class DefNewGeneration: public Generation { return n > alignment ? align_down(n, alignment) : alignment; } + size_t calculate_desired_young_gen_bytes() const; + + void expand_eden_by(size_t delta_bytes); + + void resize_inner(); + void post_resize(); + public: DefNewGeneration(ReservedSpace rs, size_t initial_byte_size, @@ -183,9 +190,8 @@ class DefNewGeneration: public Generation { HeapWord* block_start(const void* p) const; - // Allocate requested size or return null; single-threaded and lock-free versions. - HeapWord* allocate(size_t word_size); HeapWord* par_allocate(size_t word_size); + HeapWord* expand_and_allocate(size_t word_size); void gc_epilogue(); @@ -196,8 +202,8 @@ class DefNewGeneration: public Generation { // Reset for contribution of "to-space". void reset_scratch(); - // GC support - void compute_new_size(); + void resize_after_young_gc(); + void resize_after_full_gc(); bool collect(bool clear_all_soft_refs); @@ -220,13 +226,9 @@ class DefNewGeneration: public Generation { DefNewTracer* gc_tracer() const { return _gc_tracer; } - protected: - // If clear_space is true, clear the survivor spaces. Eden is - // cleared if the minimum size of eden is 0. If mangle_space - // is true, also mangle the space in debug mode. - void compute_space_boundaries(uintx minimum_eden_size, - bool clear_space, - bool mangle_space); + private: + // Initialize eden/from/to spaces. + void init_spaces(); // Return adjusted new size for NewSizeThreadIncrease. // If any overflow happens, revert to previous new size. diff --git a/src/hotspot/share/gc/serial/serialHeap.cpp b/src/hotspot/share/gc/serial/serialHeap.cpp index 3ab88da4633..3511318e169 100644 --- a/src/hotspot/share/gc/serial/serialHeap.cpp +++ b/src/hotspot/share/gc/serial/serialHeap.cpp @@ -269,9 +269,9 @@ size_t SerialHeap::max_capacity() const { } HeapWord* SerialHeap::expand_heap_and_allocate(size_t size, bool is_tlab) { - HeapWord* result = _young_gen->allocate(size); + HeapWord* result = _young_gen->expand_and_allocate(size); - if (result == nullptr) { + if (result == nullptr && !is_tlab) { result = _old_gen->expand_and_allocate(size); } @@ -388,14 +388,13 @@ bool SerialHeap::do_young_collection(bool clear_soft_refs) { // Only update stats for successful young-gc if (result) { _old_gen->update_promote_stats(); + _young_gen->resize_after_young_gc(); } if (should_verify && VerifyAfterGC) { Universe::verify("After GC"); } - _young_gen->compute_new_size(); - print_heap_change(pre_gc_values); // Track memory usage and detect low memory after GC finishes @@ -581,7 +580,7 @@ void SerialHeap::do_full_collection(bool clear_all_soft_refs) { // Adjust generation sizes. _old_gen->compute_new_size(); - _young_gen->compute_new_size(); + _young_gen->resize_after_full_gc(); _old_gen->update_promote_stats(); diff --git a/src/hotspot/share/gc/serial/serialHeap.hpp b/src/hotspot/share/gc/serial/serialHeap.hpp index 27053b4cc81..3915f8c4af9 100644 --- a/src/hotspot/share/gc/serial/serialHeap.hpp +++ b/src/hotspot/share/gc/serial/serialHeap.hpp @@ -55,10 +55,10 @@ class TenuredGeneration; // +-- generation boundary (fixed after startup) // | // |<- young gen (reserved MaxNewSize) ->|<- old gen (reserved MaxOldSize) ->| -// +-----------------+--------+--------+--------+---------------+-------------------+ -// | eden | from | to | | old | | -// | | (to) | (from) | | | | -// +-----------------+--------+--------+--------+---------------+-------------------+ +// +--------+--------+-----------------+--------+---------------+-------------------+ +// | from | to | eden | | old | | +// | (to) | (from) | | | | | +// +--------+--------+-----------------+--------+---------------+-------------------+ // |<- committed ->| |<- committed ->| // class SerialHeap : public CollectedHeap { diff --git a/src/hotspot/share/gc/shared/space.cpp b/src/hotspot/share/gc/shared/space.cpp index 08476cb2a3a..1d15fbc3fa9 100644 --- a/src/hotspot/share/gc/shared/space.cpp +++ b/src/hotspot/share/gc/shared/space.cpp @@ -53,7 +53,10 @@ void ContiguousSpace::initialize(MemRegion mr, set_bottom(bottom); set_end(end); if (clear_space) { - clear(mangle_space); + clear(SpaceDecorator::DontMangle); + } + if (ZapUnusedHeapArea && mangle_space) { + mangle_unused_area(); } } From 18fd04770294e27011bd576b5ea5fe43fa03e5e3 Mon Sep 17 00:00:00 2001 From: Justin King Date: Thu, 16 Oct 2025 19:59:13 +0000 Subject: [PATCH 0251/1639] 8369506: Bytecode rewriting causes Java heap corruption on AArch64 Co-authored-by: Man Cao Co-authored-by: Chuck Rasbold Reviewed-by: shade, aph, manc --- src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp | 11 +++++++++++ src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp | 2 ++ src/hotspot/cpu/aarch64/templateTable_aarch64.cpp | 15 ++++++++++++--- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp index 607912e6e49..6f8795494a2 100644 --- a/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/interp_masm_aarch64.cpp @@ -1704,3 +1704,14 @@ void InterpreterMacroAssembler::load_method_entry(Register cache, Register index add(cache, cache, Array::base_offset_in_bytes()); lea(cache, Address(cache, index)); } + +#ifdef ASSERT +void InterpreterMacroAssembler::verify_field_offset(Register reg) { + // Verify the field offset is not in the header, implicitly checks for 0 + Label L; + subs(zr, reg, oopDesc::base_offset_in_bytes()); + br(Assembler::GE, L); + stop("bad field offset"); + bind(L); +} +#endif diff --git a/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp b/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp index e896a2a9430..e07e6e49f53 100644 --- a/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/interp_masm_aarch64.hpp @@ -319,6 +319,8 @@ class InterpreterMacroAssembler: public MacroAssembler { void load_resolved_indy_entry(Register cache, Register index); void load_field_entry(Register cache, Register index, int bcp_offset = 1); void load_method_entry(Register cache, Register index, int bcp_offset = 1); + + void verify_field_offset(Register reg) NOT_DEBUG_RETURN; }; #endif // CPU_AARCH64_INTERP_MASM_AARCH64_HPP diff --git a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp index 5195432f54e..f4774f31bbd 100644 --- a/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/templateTable_aarch64.cpp @@ -168,6 +168,7 @@ void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg, Register temp_reg, bool load_bc_into_bc_reg/*=true*/, int byte_no) { + assert_different_registers(bc_reg, temp_reg); if (!RewriteBytecodes) return; Label L_patch_done; @@ -231,9 +232,12 @@ void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg, __ stop("patching the wrong bytecode"); __ bind(L_okay); #endif - - // patch bytecode - __ strb(bc_reg, at_bcp(0)); + // Patch bytecode with release store to coordinate with ResolvedFieldEntry loads + // in fast bytecode codelets. load_field_entry has a memory barrier that gains + // the needed ordering, together with control dependency on entering the fast codelet + // itself. + __ lea(temp_reg, at_bcp(0)); + __ stlrb(bc_reg, temp_reg); __ bind(L_patch_done); } @@ -3094,6 +3098,7 @@ void TemplateTable::fast_storefield(TosState state) // R1: field offset, R2: field holder, R5: flags load_resolved_field_entry(r2, r2, noreg, r1, r5); + __ verify_field_offset(r1); { Label notVolatile; @@ -3183,6 +3188,8 @@ void TemplateTable::fast_accessfield(TosState state) __ load_field_entry(r2, r1); __ load_sized_value(r1, Address(r2, in_bytes(ResolvedFieldEntry::field_offset_offset())), sizeof(int), true /*is_signed*/); + __ verify_field_offset(r1); + __ load_unsigned_byte(r3, Address(r2, in_bytes(ResolvedFieldEntry::flags_offset()))); // r0: object @@ -3249,7 +3256,9 @@ void TemplateTable::fast_xaccess(TosState state) __ ldr(r0, aaddress(0)); // access constant pool cache __ load_field_entry(r2, r3, 2); + __ load_sized_value(r1, Address(r2, in_bytes(ResolvedFieldEntry::field_offset_offset())), sizeof(int), true /*is_signed*/); + __ verify_field_offset(r1); // 8179954: We need to make sure that the code generated for // volatile accesses forms a sequentially-consistent set of From 0c1c86e68efcc140cefbde89b4d1d8708e931528 Mon Sep 17 00:00:00 2001 From: Patricio Chilano Mateo Date: Thu, 16 Oct 2025 21:20:42 +0000 Subject: [PATCH 0252/1639] 8370036: TestJhsdbJstackWithVirtualThread.java fails when run with -showversion Reviewed-by: ayang, cjplummer --- .../serviceability/sa/TestJhsdbJstackWithVirtualThread.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackWithVirtualThread.java b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackWithVirtualThread.java index fce9906ca94..acea00a190b 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackWithVirtualThread.java +++ b/test/hotspot/jtreg/serviceability/sa/TestJhsdbJstackWithVirtualThread.java @@ -45,7 +45,7 @@ public class TestJhsdbJstackWithVirtualThread { private static void runJstack(LingeredApp app) throws Exception { JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK("jhsdb"); - launcher.addVMArgs(Utils.getTestJavaOpts()); + launcher.addVMArgs(Utils.getFilteredTestJavaOpts("-showversion")); launcher.addToolArg("jstack"); launcher.addToolArg("--pid"); launcher.addToolArg(Long.toString(app.getPid())); From 0bdd6f0640fc25667f911228eed6a0fa118e8ff8 Mon Sep 17 00:00:00 2001 From: Francesco Andreuzzi Date: Thu, 16 Oct 2025 22:04:40 +0000 Subject: [PATCH 0253/1639] 8369734: JvmtiExport::post_class_file_load_hook return value is never used Reviewed-by: dholmes, sspitsyn --- src/hotspot/share/prims/jvmtiExport.cpp | 12 +++--------- src/hotspot/share/prims/jvmtiExport.hpp | 5 ++--- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/src/hotspot/share/prims/jvmtiExport.cpp b/src/hotspot/share/prims/jvmtiExport.cpp index fa6ede86cd9..0884fce2ff7 100644 --- a/src/hotspot/share/prims/jvmtiExport.cpp +++ b/src/hotspot/share/prims/jvmtiExport.cpp @@ -879,7 +879,6 @@ class JvmtiClassFileLoadHookPoster : public StackObj { JvmtiThreadState * _state; Klass* _class_being_redefined; JvmtiClassLoadKind _load_kind; - bool _has_been_modified; public: inline JvmtiClassFileLoadHookPoster(Symbol* h_name, Handle class_loader, @@ -896,7 +895,6 @@ class JvmtiClassFileLoadHookPoster : public StackObj { _curr_data = *data_ptr; _curr_env = nullptr; _cached_class_file_ptr = cache_ptr; - _has_been_modified = false; _state = JvmtiExport::get_jvmti_thread_state(_thread); if (_state != nullptr) { @@ -935,8 +933,6 @@ class JvmtiClassFileLoadHookPoster : public StackObj { copy_modified_data(); } - bool has_been_modified() { return _has_been_modified; } - private: void post_all_envs() { if (_load_kind != jvmti_class_load_kind_retransform) { @@ -983,7 +979,6 @@ class JvmtiClassFileLoadHookPoster : public StackObj { } if (new_data != nullptr) { // this agent has modified class data. - _has_been_modified = true; if (caching_needed && *_cached_class_file_ptr == nullptr) { // data has been changed by the new retransformable agent // and it hasn't already been cached, cache it @@ -1058,18 +1053,18 @@ bool JvmtiExport::_should_post_class_file_load_hook = false; int JvmtiExport::_should_notify_object_alloc = 0; // this entry is for class file load hook on class load, redefine and retransform -bool JvmtiExport::post_class_file_load_hook(Symbol* h_name, +void JvmtiExport::post_class_file_load_hook(Symbol* h_name, Handle class_loader, Handle h_protection_domain, unsigned char **data_ptr, unsigned char **end_ptr, JvmtiCachedClassFileData **cache_ptr) { if (JvmtiEnv::get_phase() < JVMTI_PHASE_PRIMORDIAL) { - return false; + return; } if (JavaThread::current()->should_hide_jvmti_events()) { - return false; + return; } JvmtiClassFileLoadHookPoster poster(h_name, class_loader, @@ -1077,7 +1072,6 @@ bool JvmtiExport::post_class_file_load_hook(Symbol* h_name, data_ptr, end_ptr, cache_ptr); poster.post(); - return poster.has_been_modified(); } void JvmtiExport::report_unsupported(bool on) { diff --git a/src/hotspot/share/prims/jvmtiExport.hpp b/src/hotspot/share/prims/jvmtiExport.hpp index 062057c70ab..8906d6b81df 100644 --- a/src/hotspot/share/prims/jvmtiExport.hpp +++ b/src/hotspot/share/prims/jvmtiExport.hpp @@ -377,11 +377,10 @@ class JvmtiExport : public AllStatic { static bool is_early_phase() NOT_JVMTI_RETURN_(false); static bool has_early_class_hook_env() NOT_JVMTI_RETURN_(false); static bool has_early_vmstart_env() NOT_JVMTI_RETURN_(false); - // Return true if the class was modified by the hook. - static bool post_class_file_load_hook(Symbol* h_name, Handle class_loader, + static void post_class_file_load_hook(Symbol* h_name, Handle class_loader, Handle h_protection_domain, unsigned char **data_ptr, unsigned char **end_ptr, - JvmtiCachedClassFileData **cache_ptr) NOT_JVMTI_RETURN_(false); + JvmtiCachedClassFileData **cache_ptr) NOT_JVMTI_RETURN; static void post_native_method_bind(Method* method, address* function_ptr) NOT_JVMTI_RETURN; static void post_compiled_method_load(JvmtiEnv* env, nmethod *nm) NOT_JVMTI_RETURN; static void post_compiled_method_load(nmethod *nm) NOT_JVMTI_RETURN; From 4d20f7696c015bc0e59544ff064fe0c640d61edf Mon Sep 17 00:00:00 2001 From: William Kemper Date: Fri, 17 Oct 2025 00:15:37 +0000 Subject: [PATCH 0254/1639] 8370050: Shenandoah: Obsolete ShenandoahPacing option Reviewed-by: ysr --- src/hotspot/share/runtime/arguments.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index 8b703cb442a..0d9973a1b09 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -548,6 +548,7 @@ static SpecialFlag const special_jvm_flags[] = { { "ZGenerational", JDK_Version::jdk(23), JDK_Version::jdk(24), JDK_Version::undefined() }, { "ZMarkStackSpaceLimit", JDK_Version::undefined(), JDK_Version::jdk(25), JDK_Version::undefined() }, { "G1UpdateBufferSize", JDK_Version::undefined(), JDK_Version::jdk(26), JDK_Version::jdk(27) }, + { "ShenandoahPacing", JDK_Version::jdk(25), JDK_Version::jdk(26), JDK_Version::jdk(27) }, #if defined(AARCH64) { "NearCpool", JDK_Version::undefined(), JDK_Version::jdk(25), JDK_Version::undefined() }, #endif From bd7315648f2bb18cba9cfbeca00e6132b8eb95ef Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Fri, 17 Oct 2025 00:36:54 +0000 Subject: [PATCH 0255/1639] 8369856: AOT map does not include unregistered classes Co-authored-by: Ashutosh Mehra Reviewed-by: kvn, matsaave --- .../classfile/systemDictionaryShared.cpp | 4 + .../{CDSMapReader.java => AOTMapReader.java} | 77 +++++++++++++++++-- .../cds/{CDSMapTest.java => AOTMapTest.java} | 12 +-- .../cds/appcds/aotCache/AOTMapTest.java | 55 +++++++++---- 4 files changed, 120 insertions(+), 28 deletions(-) rename test/hotspot/jtreg/runtime/cds/{CDSMapReader.java => AOTMapReader.java} (81%) rename test/hotspot/jtreg/runtime/cds/{CDSMapTest.java => AOTMapTest.java} (92%) diff --git a/src/hotspot/share/classfile/systemDictionaryShared.cpp b/src/hotspot/share/classfile/systemDictionaryShared.cpp index b092e71f4e7..2d31a7c49f6 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.cpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp @@ -1420,6 +1420,10 @@ void SystemDictionaryShared::get_all_archived_classes(bool is_static_archive, Gr get_archive(is_static_archive)->_builtin_dictionary.iterate([&] (const RunTimeClassInfo* record) { classes->append(record->klass()); }); + + get_archive(is_static_archive)->_unregistered_dictionary.iterate([&] (const RunTimeClassInfo* record) { + classes->append(record->klass()); + }); } class SharedDictionaryPrinter : StackObj { diff --git a/test/hotspot/jtreg/runtime/cds/CDSMapReader.java b/test/hotspot/jtreg/runtime/cds/AOTMapReader.java similarity index 81% rename from test/hotspot/jtreg/runtime/cds/CDSMapReader.java rename to test/hotspot/jtreg/runtime/cds/AOTMapReader.java index f25455b2f03..e407d4e2ecc 100644 --- a/test/hotspot/jtreg/runtime/cds/CDSMapReader.java +++ b/test/hotspot/jtreg/runtime/cds/AOTMapReader.java @@ -26,6 +26,7 @@ import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -33,7 +34,7 @@ import java.util.regex.Pattern; This is a simple parser for parsing the output of - java -Xshare:dump -Xlog:aot+map=debug,aot+map+oops=trace:file=cds.map:none:filesize=0 + java -Xshare:dump -Xlog:aot+map=debug,aot+map+oops=trace:file=aot.map:none:filesize=0 The map file contains patterns like this for the heap objects: @@ -59,8 +60,9 @@ more analysis on the HeapObjects. */ -public class CDSMapReader { +public class AOTMapReader { public static class MapFile { + HashSet classes = new HashSet<>(); ArrayList heapObjects = new ArrayList<>(); HashMap oopToObject = new HashMap<>(); HashMap narrowOopToObject = new HashMap<>(); @@ -80,6 +82,20 @@ public class CDSMapReader { public int heapObjectCount() { return heapObjects.size(); } + + void addClass(String className) { + classes.add(className); + } + + public boolean hasClass(String className) { + return classes.contains(className); + } + + public void shouldHaveClass(String className) { + if (!hasClass(className)) { + throw new RuntimeException("AOT map file is missing class " + className); + } + } } public static class HeapAddress { @@ -140,13 +156,17 @@ public class CDSMapReader { this.name = name; this.offset = Integer.parseInt(offset); this.referentAddress = new HeapAddress(oopStr, narrowOopStr); - this.lineCount = CDSMapReader.lineCount; + this.lineCount = AOTMapReader.lineCount; } } // 0x00000007ffc00000: 4a5b8701 00000063 00010290 00000000 00010100 fff80003 static Pattern rawDataPattern = Pattern.compile("^0x([0-9a-f]+): *( [0-9a-f]+)+ *$"); + // ------------------------------------------------------------------------------- + // Patterns for heap objects + // ------------------------------------------------------------------------------- + // (one address) // 0x00000007ffc00000: @@ Object java.lang.String static Pattern objPattern1 = Pattern.compile("^0x([0-9a-f]+): @@ Object ([^ ]*)"); @@ -179,6 +199,15 @@ public class CDSMapReader { // - injected 'module_entry' 'J' @16 0 (0x0000000000000000) static Pattern moduleEntryPattern = Pattern.compile("- injected 'module_entry' 'J' @[0-9]+[ ]+([0-9]+)"); + // ------------------------------------------------------------------------------- + // Patterns for metaspace objects + // ------------------------------------------------------------------------------- + + // 0x00000008000d1698: @@ Class 512 [Ljdk.internal.vm.FillerElement; + // 0x00000008000d18a0: @@ Class 520 java.lang.Cloneable + static Pattern classPattern = Pattern.compile("^0x([0-9a-f]+): @@ Class [ ]*([0-9]+) (.*)"); + + private static Matcher match(String line, Pattern pattern) { Matcher m = pattern.matcher(line); if (m.find()) { @@ -253,6 +282,11 @@ public class CDSMapReader { } } + private static void parseClassObject(String className, String addr, String size) throws IOException { + mapFile.addClass(className); + nextLine(); + } + static MapFile mapFile; static BufferedReader reader; static String line = null; // current line being parsed @@ -277,6 +311,8 @@ public class CDSMapReader { parseHeapObject(m.group(3), m.group(1), m.group(2)); } else if ((m = match(line, objPattern1)) != null) { parseHeapObject(m.group(2), m.group(1), null); + } else if ((m = match(line, classPattern)) != null) { + parseClassObject(m.group(3), m.group(1), m.group(2)); // name, addr, size } else { nextLine(); } @@ -303,8 +339,15 @@ public class CDSMapReader { } } + public static void validate(MapFile mapFile, String classLoadLogFile) throws IOException { + validateOops(mapFile); + if (classLoadLogFile != null) { + validateClasses(mapFile, classLoadLogFile); + } + } + // Check that each oop fields in the HeapObjects must point to a valid HeapObject. - public static void validate(MapFile mapFile) { + static void validateOops(MapFile mapFile) { int count1 = 0; int count2 = 0; for (HeapObject heapObject : mapFile.heapObjects) { @@ -333,10 +376,10 @@ public class CDSMapReader { if (mapFile.heapObjectCount() > 0) { // heapObjectCount() may be zero if the selected GC doesn't support heap object archiving. if (mapFile.stringCount <= 0) { - throw new RuntimeException("CDS map file should contain at least one string"); + throw new RuntimeException("AOT map file should contain at least one string"); } if (count1 < mapFile.stringCount) { - throw new RuntimeException("CDS map file seems incorrect: " + mapFile.heapObjectCount() + + throw new RuntimeException("AOT map file seems incorrect: " + mapFile.heapObjectCount() + " objects (" + mapFile.stringCount + " strings). Each string should" + " have one non-null oop field but we found only " + count1 + " non-null oop field references"); @@ -344,8 +387,26 @@ public class CDSMapReader { } } - public static void main(String args[]) { + // classLoadLogFile should be generated with -Xlog:class+load:file=:none:filesize=0 + // Check that every class loaded from "source: shared objects file" have an entry inside the mapFile. + static void validateClasses(MapFile mapFile, String classLoadLogFile) throws IOException { + try (BufferedReader r = new BufferedReader(new FileReader(classLoadLogFile))) { + String line; + String suffix = " source: shared objects file"; + int suffixLen = suffix.length(); + while ((line = r.readLine()) != null) { + if (line.endsWith(suffix)) { + String className = line.substring(0, line.length() - suffixLen); + if (!mapFile.hasClass(className)) { + throw new RuntimeException("AOT map file is missing class " + className); + } + } + } + } + } + + public static void main(String args[]) throws IOException { MapFile mapFile = read(args[0]); - validate(mapFile); + validate(mapFile, null); } } diff --git a/test/hotspot/jtreg/runtime/cds/CDSMapTest.java b/test/hotspot/jtreg/runtime/cds/AOTMapTest.java similarity index 92% rename from test/hotspot/jtreg/runtime/cds/CDSMapTest.java rename to test/hotspot/jtreg/runtime/cds/AOTMapTest.java index 5a9fa82552b..dff98090859 100644 --- a/test/hotspot/jtreg/runtime/cds/CDSMapTest.java +++ b/test/hotspot/jtreg/runtime/cds/AOTMapTest.java @@ -27,7 +27,7 @@ * @summary Test the contents of -Xlog:aot+map * @requires vm.cds * @library /test/lib - * @run driver/timeout=240 CDSMapTest + * @run driver/timeout=240 AOTMapTest */ import jdk.test.lib.cds.CDSOptions; @@ -37,7 +37,7 @@ import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; import java.util.ArrayList; -public class CDSMapTest { +public class AOTMapTest { public static void main(String[] args) throws Exception { doTest(false); @@ -79,8 +79,8 @@ public class CDSMapTest { .addSuffix(args); CDSTestUtils.createArchiveAndCheck(opts); - CDSMapReader.MapFile mapFile = CDSMapReader.read(mapName); - CDSMapReader.validate(mapFile); + AOTMapReader.MapFile mapFile = AOTMapReader.read(mapName); + AOTMapReader.validate(mapFile, null); return archiveName; } @@ -98,7 +98,7 @@ public class CDSMapTest { OutputAnalyzer out = CDSTestUtils.executeAndLog(pb, "exec"); out.shouldHaveExitValue(0); - CDSMapReader.MapFile mapFile = CDSMapReader.read(mapName); - CDSMapReader.validate(mapFile); + AOTMapReader.MapFile mapFile = AOTMapReader.read(mapName); + AOTMapReader.validate(mapFile, null); } } diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/AOTMapTest.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/AOTMapTest.java index bcd2c71fea0..6cbfcbbd3c3 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/AOTMapTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/AOTMapTest.java @@ -26,9 +26,10 @@ * @bug 8362566 * @summary Test the contents of -Xlog:aot+map with AOT workflow * @requires vm.cds.supports.aot.class.linking - * @library /test/lib /test/hotspot/jtreg/runtime/cds - * @build AOTMapTest + * @library /test/lib /test/hotspot/jtreg/runtime/cds /test/hotspot/jtreg/runtime/cds/appcds/test-classes + * @build AOTMapTest Hello * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar AOTMapTestApp + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar cust.jar Hello * @run driver/timeout=240 AOTMapTest AOT --two-step-training */ @@ -37,15 +38,18 @@ * @bug 8362566 * @summary Test the contents of -Xlog:aot+map with dynamic CDS archive * @requires vm.cds.supports.aot.class.linking - * @library /test/lib /test/hotspot/jtreg/runtime/cds + * @library /test/lib /test/hotspot/jtreg/runtime/cds /test/hotspot/jtreg/runtime/cds/appcds/test-classes * @build jdk.test.whitebox.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @build AOTMapTest + * @build AOTMapTest Hello * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar AOTMapTestApp + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar cust.jar Hello * @run main/othervm/timeout=240 -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. AOTMapTest DYNAMIC */ - +import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; import java.util.ArrayList; import jdk.test.lib.cds.CDSAppTester; import jdk.test.lib.helpers.ClassFileInstaller; @@ -54,6 +58,7 @@ import jdk.test.lib.Platform; public class AOTMapTest { static final String appJar = ClassFileInstaller.getJarPath("app.jar"); static final String mainClass = "AOTMapTestApp"; + static final String classLoadLogFile = "production.class.load.log"; public static void main(String[] args) throws Exception { doTest(args); @@ -63,13 +68,25 @@ public class AOTMapTest { Tester tester = new Tester(); tester.run(args); - validate(tester.dumpMapFile); - validate(tester.runMapFile); + if (tester.isDynamicWorkflow()) { + // For dynamic workflow, the AOT map file doesn't include classes in the base archive, so + // AOTMapReader.validateClasses() will fail. + validate(tester.dumpMapFile, false); + } else { + validate(tester.dumpMapFile, true); + } + validate(tester.runMapFile, true); } - static void validate(String mapFileName) { - CDSMapReader.MapFile mapFile = CDSMapReader.read(mapFileName); - CDSMapReader.validate(mapFile); + static void validate(String mapFileName, boolean checkClases) throws Exception { + AOTMapReader.MapFile mapFile = AOTMapReader.read(mapFileName); + if (checkClases) { + AOTMapReader.validate(mapFile, classLoadLogFile); + } else { + AOTMapReader.validate(mapFile, null); + } + mapFile.shouldHaveClass("AOTMapTestApp"); // built-in class + mapFile.shouldHaveClass("Hello"); // unregistered class } static class Tester extends CDSAppTester { @@ -97,12 +114,13 @@ public class AOTMapTest { // filesize=0 ensures that a large map file not broken up in multiple files. String logMapPrefix = "-Xlog:aot+map=debug,aot+map+oops=trace:file="; - String logMapSuffix = ":none:filesize=0"; + String logSuffix = ":none:filesize=0"; if (runMode == RunMode.ASSEMBLY || runMode == RunMode.DUMP_DYNAMIC) { - vmArgs.add(logMapPrefix + dumpMapFile + logMapSuffix); + vmArgs.add(logMapPrefix + dumpMapFile + logSuffix); } else if (runMode == RunMode.PRODUCTION) { - vmArgs.add(logMapPrefix + runMapFile + logMapSuffix); + vmArgs.add(logMapPrefix + runMapFile + logSuffix); + vmArgs.add("-Xlog:class+load:file=" + classLoadLogFile + logSuffix); } return vmArgs.toArray(new String[vmArgs.size()]); @@ -118,7 +136,16 @@ public class AOTMapTest { } class AOTMapTestApp { - public static void main(String[] args) { + public static void main(String[] args) throws Exception { System.out.println("Hello AOTMapTestApp"); + testCustomLoader(); + } + + static void testCustomLoader() throws Exception { + File custJar = new File("cust.jar"); + URL[] urls = new URL[] {custJar.toURI().toURL()}; + URLClassLoader loader = new URLClassLoader(urls, AOTMapTestApp.class.getClassLoader()); + Class c = loader.loadClass("Hello"); + System.out.println(c); } } From 55787fe5f52544ea902cac35f1f552e26d954167 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Fri, 17 Oct 2025 01:31:39 +0000 Subject: [PATCH 0256/1639] 8342401: [TESTBUG] javax/swing/JSpinner/8223788/JSpinnerButtonFocusTest.java test fails in ubuntu 22.04 on SBR Hosts Reviewed-by: honkar, serb --- .../8223788/JSpinnerButtonFocusTest.java | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/test/jdk/javax/swing/JSpinner/8223788/JSpinnerButtonFocusTest.java b/test/jdk/javax/swing/JSpinner/8223788/JSpinnerButtonFocusTest.java index 4060042ca4f..994a03959b2 100644 --- a/test/jdk/javax/swing/JSpinner/8223788/JSpinnerButtonFocusTest.java +++ b/test/jdk/javax/swing/JSpinner/8223788/JSpinnerButtonFocusTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,7 +63,7 @@ public class JSpinnerButtonFocusTest { robot.setAutoDelay(50); SwingUtilities.invokeAndWait(() -> { - frame = new JFrame(); + frame = new JFrame("JSpinnerButtonFocusTest"); spinner1 = new JSpinner(); spinner2 = new JSpinner(); @@ -72,6 +72,15 @@ public class JSpinnerButtonFocusTest { frame.getContentPane().add(spinner2, BorderLayout.SOUTH); editor1 = ((DefaultEditor)spinner1.getEditor()); + editor1.getTextField().addFocusListener(new FocusAdapter() { + @Override + public void focusGained(FocusEvent e) { + super.focusGained(e); + robot.keyPress(KeyEvent.VK_TAB); + robot.keyRelease(KeyEvent.VK_TAB); + latch1.countDown(); + } + }); editor1.setFocusable(false); spinner1.setFocusable(false); @@ -84,26 +93,18 @@ public class JSpinnerButtonFocusTest { frame.setFocusTraversalPolicyProvider(true); frame.setAlwaysOnTop(true); - frame.pack(); + frame.setSize(100, 100); + frame.setLocationRelativeTo(null); frame.setVisible(true); }); robot.waitForIdle(); - - editor1.getTextField().addFocusListener(new FocusAdapter() { - @Override - public void focusGained(FocusEvent e) { - super.focusGained(e); - robot.keyPress(KeyEvent.VK_TAB); - robot.keyRelease(KeyEvent.VK_TAB); - latch1.countDown(); - } - }); + robot.delay(1000); SwingUtilities.invokeAndWait(() -> { editor1.getTextField().requestFocusInWindow(); }); - if (!latch1.await(15, TimeUnit.MINUTES)) { + if (!latch1.await(1, TimeUnit.MINUTES)) { throw new RuntimeException(LF.getClassName() + ": Timeout waiting for editor1 to gain focus."); } From 31beb7d3b34c3516c326c9d29a267f6becb38805 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Fri, 17 Oct 2025 01:33:30 +0000 Subject: [PATCH 0257/1639] 8068310: [TEST_BUG] Test javax/swing/JColorChooser/Test4234761.java fails with GTKL&F Reviewed-by: serb --- .../jdk/javax/swing/JColorChooser/Test4234761.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/test/jdk/javax/swing/JColorChooser/Test4234761.java b/test/jdk/javax/swing/JColorChooser/Test4234761.java index c2b2d9ed7b9..fb55ca37feb 100644 --- a/test/jdk/javax/swing/JColorChooser/Test4234761.java +++ b/test/jdk/javax/swing/JColorChooser/Test4234761.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,10 +23,12 @@ /* * @test - * @key headful * @bug 4234761 + * @key headful * @summary RGB values sholdn't be changed in transition to HSB tab - * @author Oleg Mokhovikov + * @library /test/lib + * @build jtreg.SkippedException + * @run main Test4234761 */ import java.awt.Color; @@ -35,11 +37,17 @@ import java.beans.PropertyChangeListener; import javax.swing.JColorChooser; import javax.swing.JDialog; import javax.swing.JTabbedPane; +import javax.swing.UIManager; + +import jtreg.SkippedException; public class Test4234761 implements PropertyChangeListener { private static final Color COLOR = new Color(51, 51, 51); public static void main(String[] args) { + if (UIManager.getLookAndFeel().getName().contains("GTK")) { + throw new SkippedException("Test skipped for GTK"); + } JColorChooser chooser = new JColorChooser(COLOR); JDialog dialog = Test4177735.show(chooser); From 46c23bb1a252916096876c2ae3a72f4a525dd6f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laurent=20Bourg=C3=A8s?= Date: Fri, 17 Oct 2025 05:43:10 +0000 Subject: [PATCH 0258/1639] 8341381: Random lines appear in graphic causing by the fix of JDK-8297230 Reviewed-by: prr --- .../classes/sun/java2d/marlin/Curve.java | 53 +- .../java2d/marlin/DMarlinRenderingEngine.java | 2 +- .../classes/sun/java2d/marlin/Helpers.java | 23 +- .../classes/sun/java2d/marlin/Stroker.java | 14 +- test/jdk/sun/java2d/marlin/Bug8341381.java | 601 ++++++++++++++++++ 5 files changed, 656 insertions(+), 37 deletions(-) create mode 100644 test/jdk/sun/java2d/marlin/Bug8341381.java diff --git a/src/java.desktop/share/classes/sun/java2d/marlin/Curve.java b/src/java.desktop/share/classes/sun/java2d/marlin/Curve.java index 2ce0cd4672c..9d2c8dc2a72 100644 --- a/src/java.desktop/share/classes/sun/java2d/marlin/Curve.java +++ b/src/java.desktop/share/classes/sun/java2d/marlin/Curve.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -144,7 +144,9 @@ final class Curve { // finds points where the first and second derivative are // perpendicular. This happens when g(t) = f'(t)*f''(t) == 0 (where // * is a dot product). Unfortunately, we have to solve a cubic. - private int perpendiculardfddf(final double[] pts, final int off) { + private int perpendiculardfddf(final double[] pts, final int off, + final double A, final double B) + { assert pts.length >= off + 4; // these are the coefficients of some multiple of g(t) (not g(t), @@ -155,7 +157,7 @@ final class Curve { final double c = 2.0d * (dax * cx + day * cy) + dbx * dbx + dby * dby; final double d = dbx * cx + dby * cy; - return Helpers.cubicRootsInAB(a, b, c, d, pts, off, 0.0d, 1.0d); + return Helpers.cubicRootsInAB(a, b, c, d, pts, off, A, B); } // Tries to find the roots of the function ROC(t)-w in [0, 1). It uses @@ -171,35 +173,43 @@ final class Curve { // at most 4 sub-intervals of (0,1). ROC has asymptotes at inflection // points, so roc-w can have at least 6 roots. This shouldn't be a // problem for what we're trying to do (draw a nice looking curve). - int rootsOfROCMinusW(final double[] roots, final int off, final double w2, final double err) { + int rootsOfROCMinusW(final double[] roots, final int off, final double w2, + final double A, final double B) + { // no OOB exception, because by now off<=6, and roots.length >= 10 assert off <= 6 && roots.length >= 10; int ret = off; - final int end = off + perpendiculardfddf(roots, off); + final int end = off + perpendiculardfddf(roots, off, A, B); + Helpers.isort(roots, off, end); roots[end] = 1.0d; // always check interval end points - double t0 = 0.0d, ft0 = ROCsq(t0) - w2; + double t0 = 0.0d; + double ft0 = eliminateInf(ROCsq(t0) - w2); + double t1, ft1; for (int i = off; i <= end; i++) { - double t1 = roots[i], ft1 = ROCsq(t1) - w2; + t1 = roots[i]; + ft1 = eliminateInf(ROCsq(t1) - w2); if (ft0 == 0.0d) { roots[ret++] = t0; } else if (ft1 * ft0 < 0.0d) { // have opposite signs // (ROC(t)^2 == w^2) == (ROC(t) == w) is true because // ROC(t) >= 0 for all t. - roots[ret++] = falsePositionROCsqMinusX(t0, t1, w2, err); + roots[ret++] = falsePositionROCsqMinusX(t0, t1, ft0, ft1, w2, A); // A = err } t0 = t1; ft0 = ft1; } - return ret - off; } - private static double eliminateInf(final double x) { - return (x == Double.POSITIVE_INFINITY ? Double.MAX_VALUE : - (x == Double.NEGATIVE_INFINITY ? Double.MIN_VALUE : x)); + private final static double MAX_ROC_SQ = 1e20; + + private static double eliminateInf(final double x2) { + // limit the value of x to avoid numerical problems (smaller step): + // must handle NaN and +Infinity: + return (x2 <= MAX_ROC_SQ) ? x2 : MAX_ROC_SQ; } // A slight modification of the false position algorithm on wikipedia. @@ -210,17 +220,18 @@ final class Curve { // and turn out. Same goes for the newton's method // algorithm in Helpers.java private double falsePositionROCsqMinusX(final double t0, final double t1, + final double ft0, final double ft1, final double w2, final double err) { final int iterLimit = 100; int side = 0; - double t = t1, ft = eliminateInf(ROCsq(t) - w2); - double s = t0, fs = eliminateInf(ROCsq(s) - w2); + double s = t0, fs = eliminateInf(ft0); + double t = t1, ft = eliminateInf(ft1); double r = s, fr; - for (int i = 0; i < iterLimit && Math.abs(t - s) > err * Math.abs(t + s); i++) { + for (int i = 0; i < iterLimit && Math.abs(t - s) > err; i++) { r = (fs * t - ft * s) / (fs - ft); - fr = ROCsq(r) - w2; + fr = eliminateInf(ROCsq(r) - w2); if (sameSign(fr, ft)) { ft = fr; t = r; if (side < 0) { @@ -241,7 +252,7 @@ final class Curve { break; } } - return r; + return (Math.abs(ft) <= Math.abs(fs)) ? t : s; } private static boolean sameSign(final double x, final double y) { @@ -256,9 +267,9 @@ final class Curve { final double dy = t * (t * day + dby) + cy; final double ddx = 2.0d * dax * t + dbx; final double ddy = 2.0d * day * t + dby; - final double dx2dy2 = dx * dx + dy * dy; - final double ddx2ddy2 = ddx * ddx + ddy * ddy; - final double ddxdxddydy = ddx * dx + ddy * dy; - return dx2dy2 * ((dx2dy2 * dx2dy2) / (dx2dy2 * ddx2ddy2 - ddxdxddydy * ddxdxddydy)); + final double dx2dy2 = dx * dx + dy * dy; // positive + final double dxddyddxdy = dx * ddy - dy * ddx; + // may return +Infinity if dxddyddxdy = 0 or NaN if 0/0: + return (dx2dy2 * dx2dy2 * dx2dy2) / (dxddyddxdy * dxddyddxdy); // both positive } } diff --git a/src/java.desktop/share/classes/sun/java2d/marlin/DMarlinRenderingEngine.java b/src/java.desktop/share/classes/sun/java2d/marlin/DMarlinRenderingEngine.java index 66eb9334e86..f829872a8a8 100644 --- a/src/java.desktop/share/classes/sun/java2d/marlin/DMarlinRenderingEngine.java +++ b/src/java.desktop/share/classes/sun/java2d/marlin/DMarlinRenderingEngine.java @@ -564,7 +564,7 @@ public final class DMarlinRenderingEngine extends RenderingEngine } private static boolean nearZero(final double num) { - return Math.abs(num) < 2.0d * Math.ulp(num); + return Math.abs(num) < 2.0d * Helpers.ulp(num); } abstract static class NormalizingPathIterator implements PathIterator { diff --git a/src/java.desktop/share/classes/sun/java2d/marlin/Helpers.java b/src/java.desktop/share/classes/sun/java2d/marlin/Helpers.java index 0aed05ab506..926533cdb2b 100644 --- a/src/java.desktop/share/classes/sun/java2d/marlin/Helpers.java +++ b/src/java.desktop/share/classes/sun/java2d/marlin/Helpers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,12 +31,19 @@ import sun.java2d.marlin.stats.StatLong; final class Helpers implements MarlinConst { + private final static double T_ERR = 1e-4; + private final static double T_A = T_ERR; + private final static double T_B = 1.0 - T_ERR; + private static final double EPS = 1e-9d; private Helpers() { throw new Error("This is a non instantiable class"); } + /** use lower precision like former Pisces and Marlin (float-precision) */ + static double ulp(final double value) { return Math.ulp((float)value); } + static boolean within(final double x, final double y) { return within(x, y, EPS); } @@ -322,10 +329,10 @@ final class Helpers implements MarlinConst { // now we must subdivide at points where one of the offset curves will have // a cusp. This happens at ts where the radius of curvature is equal to w. - ret += c.rootsOfROCMinusW(ts, ret, w2, 0.0001d); + ret += c.rootsOfROCMinusW(ts, ret, w2, T_A, T_B); - ret = filterOutNotInAB(ts, 0, ret, 0.0001d, 0.9999d); - isort(ts, ret); + ret = filterOutNotInAB(ts, 0, ret, T_A, T_B); + isort(ts, 0, ret); return ret; } @@ -354,7 +361,7 @@ final class Helpers implements MarlinConst { if ((outCodeOR & OUTCODE_BOTTOM) != 0) { ret += curve.yPoints(ts, ret, clipRect[1]); } - isort(ts, ret); + isort(ts, 0, ret); return ret; } @@ -374,11 +381,11 @@ final class Helpers implements MarlinConst { } } - static void isort(final double[] a, final int len) { - for (int i = 1, j; i < len; i++) { + static void isort(final double[] a, final int off, final int len) { + for (int i = off + 1, j; i < len; i++) { final double ai = a[i]; j = i - 1; - for (; j >= 0 && a[j] > ai; j--) { + for (; j >= off && a[j] > ai; j--) { a[j + 1] = a[j]; } a[j + 1] = ai; diff --git a/src/java.desktop/share/classes/sun/java2d/marlin/Stroker.java b/src/java.desktop/share/classes/sun/java2d/marlin/Stroker.java index 59f93ed7d6d..1c257bc13d9 100644 --- a/src/java.desktop/share/classes/sun/java2d/marlin/Stroker.java +++ b/src/java.desktop/share/classes/sun/java2d/marlin/Stroker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -886,8 +886,8 @@ final class Stroker implements StartFlagPathConsumer2D, MarlinConst { // if p1 == p2 && p3 == p4: draw line from p1->p4, unless p1 == p4, // in which case ignore if p1 == p2 - final boolean p1eqp2 = Helpers.withinD(dx1, dy1, 6.0d * Math.ulp(y2)); - final boolean p3eqp4 = Helpers.withinD(dx4, dy4, 6.0d * Math.ulp(y4)); + final boolean p1eqp2 = Helpers.withinD(dx1, dy1, 6.0d * Helpers.ulp(y2)); + final boolean p3eqp4 = Helpers.withinD(dx4, dy4, 6.0d * Helpers.ulp(y4)); if (p1eqp2 && p3eqp4) { return getLineOffsets(x1, y1, x4, y4, leftOff, rightOff); @@ -905,7 +905,7 @@ final class Stroker implements StartFlagPathConsumer2D, MarlinConst { final double l1sq = dx1 * dx1 + dy1 * dy1; final double l4sq = dx4 * dx4 + dy4 * dy4; - if (Helpers.within(dotsq, l1sq * l4sq, 4.0d * Math.ulp(dotsq))) { + if (Helpers.within(dotsq, l1sq * l4sq, 4.0d * Helpers.ulp(dotsq))) { return getLineOffsets(x1, y1, x4, y4, leftOff, rightOff); } @@ -1078,8 +1078,8 @@ final class Stroker implements StartFlagPathConsumer2D, MarlinConst { // equal if they're very close to each other. // if p1 == p2 or p2 == p3: draw line from p1->p3 - final boolean p1eqp2 = Helpers.withinD(dx12, dy12, 6.0d * Math.ulp(y2)); - final boolean p2eqp3 = Helpers.withinD(dx23, dy23, 6.0d * Math.ulp(y3)); + final boolean p1eqp2 = Helpers.withinD(dx12, dy12, 6.0d * Helpers.ulp(y2)); + final boolean p2eqp3 = Helpers.withinD(dx23, dy23, 6.0d * Helpers.ulp(y3)); if (p1eqp2 || p2eqp3) { return getLineOffsets(x1, y1, x3, y3, leftOff, rightOff); @@ -1091,7 +1091,7 @@ final class Stroker implements StartFlagPathConsumer2D, MarlinConst { final double l1sq = dx12 * dx12 + dy12 * dy12; final double l3sq = dx23 * dx23 + dy23 * dy23; - if (Helpers.within(dotsq, l1sq * l3sq, 4.0d * Math.ulp(dotsq))) { + if (Helpers.within(dotsq, l1sq * l3sq, 4.0d * Helpers.ulp(dotsq))) { return getLineOffsets(x1, y1, x3, y3, leftOff, rightOff); } diff --git a/test/jdk/sun/java2d/marlin/Bug8341381.java b/test/jdk/sun/java2d/marlin/Bug8341381.java new file mode 100644 index 00000000000..b469ac49313 --- /dev/null +++ b/test/jdk/sun/java2d/marlin/Bug8341381.java @@ -0,0 +1,601 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.BasicStroke; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.Stroke; +import java.awt.geom.AffineTransform; +import java.awt.geom.CubicCurve2D; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.awt.image.Raster; +import java.io.File; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Locale; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.logging.Handler; +import java.util.logging.LogRecord; +import java.util.logging.Logger; + +import javax.imageio.ImageIO; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import javax.swing.Timer; + +import static java.lang.System.out; + +/** + * @test + * @bug 8341381 + * @summary fix cubic offsetting issue (numerical accuracy) + * @run main/othervm/timeout=20 Bug8341381 + * @modules java.desktop/sun.java2d.marlin + */ +public final class Bug8341381 { + + static final boolean SHOW_GUI = false; + + static final boolean CHECK_PIXELS = true; + static final boolean TRACE_ALL = false; + static final boolean TRACE_CHECK_PIXELS = false; + + static final boolean SAVE_IMAGE = false; + + static final boolean INTENSIVE = false; + + static final double DPI = 96; + static final float STROKE_WIDTH = 15f; + + // delay is 1 frame at 60hz + static final int DELAY = 16; + // off-screen test step (1.0 by default) + static final double STEP = (INTENSIVE) ? 1.0 / 117 : 1.0; + + // stats: + static int N_TEST = 0; + static int N_FAIL = 0; + + static final AtomicBoolean isMarlin = new AtomicBoolean(); + static final CountDownLatch latch = new CountDownLatch(1); + + public static void main(final String[] args) { + Locale.setDefault(Locale.US); + + // FIRST: Get Marlin runtime state from its log: + + // initialize j.u.l Logger: + final Logger log = Logger.getLogger("sun.java2d.marlin"); + log.addHandler(new Handler() { + @Override + public void publish(LogRecord record) { + final String msg = record.getMessage(); + if (msg != null) { + // last space to avoid matching other settings: + if (msg.startsWith("sun.java2d.renderer ")) { + isMarlin.set(msg.contains("DMarlinRenderingEngine")); + } + } + + final Throwable th = record.getThrown(); + // detect any Throwable: + if (th != null) { + out.println("Test failed:\n" + record.getMessage()); + th.printStackTrace(out); + throw new RuntimeException("Test failed: ", th); + } + } + + @Override + public void flush() { + } + + @Override + public void close() throws SecurityException { + } + }); + + out.println("Bug8341381: start"); + final long startTime = System.currentTimeMillis(); + + // enable Marlin logging & internal checks: + System.setProperty("sun.java2d.renderer.log", "true"); + System.setProperty("sun.java2d.renderer.useLogger", "true"); + + try { + startTest(); + + out.println("WAITING ..."); + latch.await(15, TimeUnit.SECONDS); // 2s typically + + if (isMarlin.get()) { + out.println("Marlin renderer used at runtime."); + } else { + throw new RuntimeException("Marlin renderer NOT used at runtime !"); + } + + // show test report: + out.println("TESTS: " + N_TEST + " FAILS: " + N_FAIL); + + if (N_FAIL > 0) { + throw new RuntimeException("Bug8341381: " + N_FAIL + " / " + N_TEST + " test(s) failed !"); + } + + } catch (InterruptedException ie) { + throw new RuntimeException(ie); + } catch (InvocationTargetException ite) { + throw new RuntimeException(ite); + } finally { + final double elapsed = (System.currentTimeMillis() - startTime) / 1000.0; + out.println("Bug8341381: end (" + elapsed + " s)"); + } + } + + private static void startTest() throws InterruptedException, InvocationTargetException { + if (SHOW_GUI) { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + final JFrame viewer = new JFrame(); + viewer.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + viewer.setContentPane(new CanvasPanel(viewer)); + viewer.pack(); + viewer.setVisible(true); + } + }); + return; + } else { + out.println("STEP: " + STEP); + new Thread(new Runnable() { + @Override + public void run() { + final Context ctx = new Context(); + final Dimension initialDim = ctx.bugDisplay.getSize(DPI); + + double w = initialDim.width; + double h = initialDim.height; + do { + ctx.shouldScale(w, h); + ctx.paintImage(); + + // resize component: + w -= STEP; + h -= STEP; + + } while (ctx.iterate()); + } + }).start(); + } + } + + static final class Context { + + final BugDisplay bugDisplay = new BugDisplay(); + double width = 0.0, height = 0.0; + + BufferedImage bimg = null; + + boolean shouldScale(final double w, final double h) { + if ((w != width) || (h != height) || !bugDisplay.isScaled) { + width = w; + height = h; + bugDisplay.scale(width, height); + N_TEST++; + return true; + } + return false; + } + + void paintImage() { + final int w = bugDisplay.canvasWidth; + final int h = bugDisplay.canvasHeight; + + if ((bimg == null) || (w > bimg.getWidth()) || (h > bimg.getHeight())) { + bimg = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB_PRE); + } + final Graphics gi = bimg.getGraphics(); + try { + bugDisplay.paint(gi); + } finally { + gi.dispose(); + } + if (!bugDisplay.checkImage(bimg)) { + N_FAIL++; + } + } + + boolean iterate() { + if ((bugDisplay.canvasWidth > 10) || (bugDisplay.canvasHeight > 10)) { + // continue: + return true; + } + out.println("Stop"); + latch.countDown(); + return false; + } + } + + static final class CanvasPanel extends JPanel { + private static final long serialVersionUID = 1L; + + private final Context ctx = new Context(); + private boolean resized = false; + private Timer timer = null; + + public CanvasPanel(final JFrame frame) { + timer = new Timer(DELAY, e -> { + if (resized) { + resized = false; + + if (ctx.iterate()) { + // resize component: + setSize((int) Math.round(ctx.width - 1), (int) Math.round(ctx.height - 1)); + } else { + timer.stop(); + if (frame != null) { + frame.setVisible(false); + } + } + } + }); + timer.setCoalesce(true); + timer.setRepeats(true); + timer.start(); + } + + @Override + public void paint(final Graphics g) { + final Dimension dim = getSize(); + if (ctx.shouldScale(dim.width, dim.height)) { + this.resized = true; + } + super.paint(g); + + // paint on buffered image: + if (CHECK_PIXELS) { + final int w = ctx.bugDisplay.canvasWidth; + final int h = ctx.bugDisplay.canvasHeight; + if (this.resized) { + ctx.paintImage(); + } + g.drawImage(ctx.bimg.getSubimage(0, 0, w, h), 0, 0, null); + } else { + ctx.bugDisplay.paint(g); + } + } + + @Override + public Dimension getPreferredSize() { + return ctx.bugDisplay.getSize(DPI); + } + } + + static final class BugDisplay { + + boolean isScaled = false; + int canvasWidth; + int canvasHeight; + + private final static java.util.List curves1 = Arrays.asList( + new CubicCurve2D.Double(2191.0, 7621.0, 2191.0, 7619.0, 2191.0, 7618.0, 2191.0, 7617.0), + new CubicCurve2D.Double(2191.0, 7617.0, 2191.0, 7617.0, 2191.0, 7616.0, 2191.0, 7615.0), + new CubicCurve2D.Double(2198.0, 7602.0, 2200.0, 7599.0, 2203.0, 7595.0, 2205.0, 7590.0), + new CubicCurve2D.Double(2205.0, 7590.0, 2212.0, 7580.0, 2220.0, 7571.0, 2228.0, 7563.0), + new CubicCurve2D.Double(2228.0, 7563.0, 2233.0, 7557.0, 2239.0, 7551.0, 2245.0, 7546.0), + new CubicCurve2D.Double(2245.0, 7546.0, 2252.0, 7540.0, 2260.0, 7534.0, 2267.0, 7528.0), + new CubicCurve2D.Double(2267.0, 7528.0, 2271.0, 7526.0, 2275.0, 7524.0, 2279.0, 7521.0), + new CubicCurve2D.Double(2279.0, 7521.0, 2279.0, 7520.0, 2280.0, 7520.0, 2281.0, 7519.0) + ); + private final static java.util.List curves2 = Arrays.asList( + new CubicCurve2D.Double(2281.0, 7519.0, 2282.0, 7518.0, 2282.0, 7517.0, 2283.0, 7516.0), + new CubicCurve2D.Double(2283.0, 7516.0, 2284.0, 7515.0, 2284.0, 7515.0, 2285.0, 7514.0), + new CubicCurve2D.Double(2291.0, 7496.0, 2292.0, 7495.0, 2292.0, 7494.0, 2291.0, 7493.0), + new CubicCurve2D.Double(2291.0, 7493.0, 2290.0, 7492.0, 2290.0, 7492.0, 2289.0, 7492.0), + new CubicCurve2D.Double(2289.0, 7492.0, 2288.0, 7491.0, 2286.0, 7492.0, 2285.0, 7492.0), + new CubicCurve2D.Double(2262.0, 7496.0, 2260.0, 7497.0, 2259.0, 7497.0, 2257.0, 7498.0), + new CubicCurve2D.Double(2257.0, 7498.0, 2254.0, 7498.0, 2251.0, 7499.0, 2248.0, 7501.0), + new CubicCurve2D.Double(2248.0, 7501.0, 2247.0, 7501.0, 2245.0, 7502.0, 2244.0, 7503.0), + new CubicCurve2D.Double(2207.0, 7523.0, 2203.0, 7525.0, 2199.0, 7528.0, 2195.0, 7530.0), + new CubicCurve2D.Double(2195.0, 7530.0, 2191.0, 7534.0, 2186.0, 7538.0, 2182.0, 7541.0) + ); + private final static java.util.List curves3 = Arrays.asList( + new CubicCurve2D.Double(2182.0, 7541.0, 2178.0, 7544.0, 2174.0, 7547.0, 2170.0, 7551.0), + new CubicCurve2D.Double(2170.0, 7551.0, 2164.0, 7556.0, 2158.0, 7563.0, 2152.0, 7569.0), + new CubicCurve2D.Double(2152.0, 7569.0, 2148.0, 7573.0, 2145.0, 7577.0, 2141.0, 7582.0), + new CubicCurve2D.Double(2141.0, 7582.0, 2138.0, 7588.0, 2134.0, 7595.0, 2132.0, 7602.0), + new CubicCurve2D.Double(2132.0, 7602.0, 2132.0, 7605.0, 2131.0, 7608.0, 2131.0, 7617.0), + new CubicCurve2D.Double(2131.0, 7617.0, 2131.0, 7620.0, 2131.0, 7622.0, 2131.0, 7624.0), + new CubicCurve2D.Double(2131.0, 7624.0, 2131.0, 7630.0, 2132.0, 7636.0, 2135.0, 7641.0), + new CubicCurve2D.Double(2135.0, 7641.0, 2136.0, 7644.0, 2137.0, 7647.0, 2139.0, 7650.0), + new CubicCurve2D.Double(2139.0, 7650.0, 2143.0, 7658.0, 2149.0, 7664.0, 2155.0, 7670.0), + new CubicCurve2D.Double(2155.0, 7670.0, 2160.0, 7676.0, 2165.0, 7681.0, 2171.0, 7686.0) + ); + private final static java.util.List curves4 = Arrays.asList( + new CubicCurve2D.Double(2171.0, 7686.0, 2174.0, 7689.0, 2177.0, 7692.0, 2180.0, 7694.0), + new CubicCurve2D.Double(2180.0, 7694.0, 2185.0, 7698.0, 2191.0, 7702.0, 2196.0, 7706.0), + new CubicCurve2D.Double(2196.0, 7706.0, 2199.0, 7708.0, 2203.0, 7711.0, 2207.0, 7713.0), + new CubicCurve2D.Double(2244.0, 7734.0, 2245.0, 7734.0, 2247.0, 7735.0, 2248.0, 7736.0), + new CubicCurve2D.Double(2248.0, 7736.0, 2251.0, 7738.0, 2254.0, 7739.0, 2257.0, 7739.0), + new CubicCurve2D.Double(2257.0, 7739.0, 2259.0, 7739.0, 2260.0, 7739.0, 2262.0, 7740.0), + new CubicCurve2D.Double(2285.0, 7745.0, 2286.0, 7745.0, 2288.0, 7745.0, 2289.0, 7745.0), + new CubicCurve2D.Double(2289.0, 7745.0, 2290.0, 7745.0, 2290.0, 7744.0, 2291.0, 7743.0), + new CubicCurve2D.Double(2291.0, 7743.0, 2292.0, 7742.0, 2292.0, 7741.0, 2291.0, 7740.0), + new CubicCurve2D.Double(2285.0, 7722.0, 2284.0, 7721.0, 2284.0, 7721.0, 2283.0, 7720.0), + new CubicCurve2D.Double(2283.0, 7720.0, 2282.0, 7719.0, 2282.0, 7719.0, 2281.0, 7718.0), + new CubicCurve2D.Double(2281.0, 7718.0, 2280.0, 7717.0, 2279.0, 7716.0, 2279.0, 7716.0), + new CubicCurve2D.Double(2279.0, 7716.0, 2275.0, 7712.0, 2271.0, 7710.0, 2267.0, 7708.0), + new CubicCurve2D.Double(2267.0, 7708.0, 2260.0, 7702.0, 2252.0, 7697.0, 2245.0, 7691.0), + new CubicCurve2D.Double(2245.0, 7691.0, 2239.0, 7685.0, 2233.0, 7679.0, 2228.0, 7673.0), + new CubicCurve2D.Double(2228.0, 7673.0, 2220.0, 7665.0, 2212.0, 7656.0, 2205.0, 7646.0), + new CubicCurve2D.Double(2205.0, 7646.0, 2203.0, 7641.0, 2200.0, 7637.0, 2198.0, 7634.0) + ); + + private final static Point2D.Double[] extent = {new Point2D.Double(0.0, 0.0), new Point2D.Double(7777.0, 10005.0)}; + + private final static Stroke STROKE = new BasicStroke(STROKE_WIDTH); + private final static Stroke STROKE_DASHED = new BasicStroke(STROKE_WIDTH, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, + 10.0f, new float[] {100f, 0f}, 0.0f); + + // members: + private final java.util.List allCurves = new ArrayList<>(); + private final Rectangle2D bboxAllCurves = new Rectangle2D.Double(); + + BugDisplay() { + allCurves.addAll(curves1); + allCurves.addAll(curves2); + allCurves.addAll(curves3); + allCurves.addAll(curves4); + + // initialize bounding box: + double x1 = Double.POSITIVE_INFINITY; + double y1 = Double.POSITIVE_INFINITY; + double x2 = Double.NEGATIVE_INFINITY; + double y2 = Double.NEGATIVE_INFINITY; + + for (final CubicCurve2D c : allCurves) { + final Rectangle2D r = c.getBounds2D(); + if (r.getMinX() < x1) { + x1 = r.getMinX(); + } + if (r.getMinY() < y1) { + y1 = r.getMinY(); + } + if (r.getMaxX() > x2) { + x2 = r.getMaxX(); + } + if (r.getMaxY() > y2) { + y2 = r.getMaxY(); + } + } + // add margin of 10%: + final double m = 1.1 * STROKE_WIDTH; + bboxAllCurves.setFrameFromDiagonal(x1 - m, y1 - m, x2 + m, y2 + m); + } + + public void paint(final Graphics g) { + final Graphics2D g2d = (Graphics2D) g; + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF); + g2d.setColor(Color.WHITE); + g2d.fillRect(0, 0, this.canvasWidth, this.canvasHeight); + + // ------ scale + final AffineTransform tx_orig = g2d.getTransform(); + final AffineTransform tx = getDrawTransform(); + g2d.transform(tx); + + // draw bbox: + if (!CHECK_PIXELS) { + g2d.setColor(Color.RED); + g2d.setStroke(STROKE); + g2d.draw(bboxAllCurves); + } + // draw curves: + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE); + g2d.setColor(Color.BLACK); + + // dasher + stroker: + g2d.setStroke(STROKE_DASHED); + this.allCurves.forEach(g2d::draw); + + // reset + g2d.setTransform(tx_orig); + } + + private AffineTransform getDrawTransform() { + // ------ scale + double minX = extent[0].x, maxX = extent[1].x; + double minY = extent[0].y, maxY = extent[1].y; + + // we're scaling and respecting the proportions, check which scale to use + double sx = this.canvasWidth / Math.abs(maxX - minX); + double sy = this.canvasHeight / Math.abs(maxY - minY); + double s = Math.min(sx, sy); + + double m00, m11, m02, m12; + if (minX < maxX) { + m00 = s; + m02 = -s * minX; + } else { + // inverted X axis + m00 = -s; + m02 = this.canvasWidth + s * maxX; + } + if (minY < maxY) { + m11 = s; + m12 = -s * minY; + } else { + // inverted Y axis + m11 = -s; + m12 = this.canvasHeight + s * maxY; + } + + // scale to the available view port + AffineTransform scaleTransform = new AffineTransform(m00, 0, 0, m11, m02, m12); + + // invert the Y axis since (0, 0) is at top left for AWT + AffineTransform invertY = new AffineTransform(1, 0, 0, -1, 0, this.canvasHeight); + invertY.concatenate(scaleTransform); + + return invertY; + } + + public Dimension getSize(double dpi) { + double metricScalingFactor = 0.02539999969303608; + // 1 inch = 25,4 millimeter + final double factor = dpi * metricScalingFactor / 25.4; + + int width = (int) Math.ceil(Math.abs(extent[1].x - extent[0].x) * factor); + int height = (int) Math.ceil(Math.abs(extent[1].y - extent[0].y) * factor); + + return new Dimension(width, height); + } + + public void scale(double w, double h) { + double extentWidth = Math.abs(extent[1].x - extent[0].x); + double extentHeight = Math.abs(extent[1].y - extent[0].y); + + double fx = w / extentWidth; + if (fx * extentHeight > h) { + fx = h / extentHeight; + } + this.canvasWidth = (int) Math.round(fx * extentWidth); + this.canvasHeight = (int) Math.round(fx * extentHeight); + + // out.println("canvas scaled (" + canvasWidth + " x " + canvasHeight + ")"); + + this.isScaled = true; + } + + protected boolean checkImage(BufferedImage image) { + final AffineTransform tx = getDrawTransform(); + + final Point2D pMin = new Point2D.Double(bboxAllCurves.getMinX(), bboxAllCurves.getMinY()); + final Point2D pMax = new Point2D.Double(bboxAllCurves.getMaxX(), bboxAllCurves.getMaxY()); + + final Point2D tMin = tx.transform(pMin, null); + final Point2D tMax = tx.transform(pMax, null); + + int xMin = (int) tMin.getX(); + int xMax = (int) tMax.getX(); + if (xMin > xMax) { + int t = xMin; + xMin = xMax; + xMax = t; + } + + int yMin = (int) tMin.getY(); + int yMax = (int) tMax.getY(); + if (yMin > yMax) { + int t = yMin; + yMin = yMax; + yMax = t; + } + // add pixel margin (AA): + xMin -= 3; + xMax += 4; + yMin -= 3; + yMax += 4; + + if (xMin < 0 || xMax > image.getWidth() + || yMin < 0 || yMax > image.getHeight()) { + return true; + } + + // out.println("Checking rectangle: " + tMin + " to " + tMax); + // out.println("X min: " + xMin + " - max: " + xMax); + // out.println("Y min: " + yMin + " - max: " + yMax); + + final Raster raster = image.getData(); + final int expected = Color.WHITE.getRGB(); + int nBadPixels = 0; + + // horizontal lines: + for (int x = xMin; x <= xMax; x++) { + if (!checkPixel(raster, x, yMin, expected)) { + nBadPixels++; + } + if (!checkPixel(raster, x, yMax, expected)) { + nBadPixels++; + } + } + + // vertical lines: + for (int y = yMin; y <= yMax; y++) { + if (!checkPixel(raster, xMin, y, expected)) { + nBadPixels++; + } + if (!checkPixel(raster, xMax, y, expected)) { + nBadPixels++; + } + } + + if (nBadPixels != 0) { + out.println("(" + canvasWidth + " x " + canvasHeight + ") BAD pixels = " + nBadPixels); + + if (SAVE_IMAGE) { + try { + final File file = new File("Bug8341381-" + canvasWidth + "-" + canvasHeight + ".png"); + + out.println("Writing file: " + file.getAbsolutePath()); + ImageIO.write(image.getSubimage(0, 0, canvasWidth, canvasHeight), "PNG", file); + } catch (IOException ioe) { + ioe.printStackTrace(); + } + } + return false; + } else if (TRACE_ALL) { + out.println("(" + canvasWidth + " x " + canvasHeight + ") OK"); + } + return true; + } + + private final static int[] TMP_RGB = new int[1]; + + private static boolean checkPixel(final Raster raster, + final int x, final int y, + final int expected) { + + final int[] rgb = (int[]) raster.getDataElements(x, y, TMP_RGB); + + if (rgb[0] != expected) { + if (TRACE_CHECK_PIXELS) { + out.println("bad pixel at (" + x + ", " + y + ") = " + rgb[0] + + " expected = " + expected); + } + return false; + } + return true; + } + } +} From a22438ddc5949fcfb6f773bd8dc080cd8a1f2710 Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Fri, 17 Oct 2025 08:16:59 +0000 Subject: [PATCH 0259/1639] 8369924: Remove test/jdk/javax/management/remote/mandatory/loading/MissingClassTest.java from problemlist Reviewed-by: sspitsyn --- test/jdk/ProblemList-Virtual.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/jdk/ProblemList-Virtual.txt b/test/jdk/ProblemList-Virtual.txt index 37c2c447efa..dcd4dbac310 100644 --- a/test/jdk/ProblemList-Virtual.txt +++ b/test/jdk/ProblemList-Virtual.txt @@ -30,8 +30,6 @@ com/sun/jdi/EATests.java#id0 8264699 generic- com/sun/jdi/ExceptionEvents.java 8278470 generic-all com/sun/jdi/RedefineCrossStart.java 8278470 generic-all -javax/management/remote/mandatory/loading/MissingClassTest.java 8145413 windows-x64 - java/lang/ScopedValue/StressStackOverflow.java#default 8309646 generic-all java/lang/ScopedValue/StressStackOverflow.java#no-TieredCompilation 8309646 generic-all java/lang/ScopedValue/StressStackOverflow.java#TieredStopAtLevel1 8309646 generic-all From 9b9559a2e33827126e1aeab7bf6f4861acaae109 Mon Sep 17 00:00:00 2001 From: David Briemann Date: Fri, 17 Oct 2025 08:59:55 +0000 Subject: [PATCH 0260/1639] 8369979: Flag UsePopCountInstruction was accidentally disabled on PPC64 Reviewed-by: aph, mdoerr --- src/hotspot/cpu/ppc/vm_version_ppc.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/hotspot/cpu/ppc/vm_version_ppc.cpp b/src/hotspot/cpu/ppc/vm_version_ppc.cpp index e2dfd4ecec9..8b1de754650 100644 --- a/src/hotspot/cpu/ppc/vm_version_ppc.cpp +++ b/src/hotspot/cpu/ppc/vm_version_ppc.cpp @@ -99,6 +99,10 @@ void VM_Version::initialize() { FLAG_SET_ERGO(TrapBasedRangeChecks, false); } + if (FLAG_IS_DEFAULT(UsePopCountInstruction)) { + FLAG_SET_ERGO(UsePopCountInstruction, true); + } + if (PowerArchitecturePPC64 >= 9) { // Performance is good since Power9. if (FLAG_IS_DEFAULT(SuperwordUseVSX)) { From e62a7fa3832bbba11e6d630015f85ae945fac824 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Fri, 17 Oct 2025 09:02:09 +0000 Subject: [PATCH 0261/1639] 8342659: Test vmTestbase/nsk/jdi/ObjectReference/referringObjects/referringObjects002/referringObjects002.java failed: Class nsk.share.jdi.TestClass1 was not unloaded Co-authored-by: Chris Plummer Reviewed-by: sspitsyn, cjplummer --- .../vmTestbase/nsk/share/ClassUnloader.java | 51 ++++++------------- .../nsk/share/jpda/AbstractDebuggeeTest.java | 12 +---- 2 files changed, 17 insertions(+), 46 deletions(-) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/ClassUnloader.java b/test/hotspot/jtreg/vmTestbase/nsk/share/ClassUnloader.java index 5ea01fb3af4..e3b6693657c 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/ClassUnloader.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/ClassUnloader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,7 @@ package nsk.share; -import java.lang.ref.Cleaner; +import java.lang.ref.PhantomReference; import java.util.*; import nsk.share.gc.gp.*; import nsk.share.test.ExecutionController; @@ -77,19 +77,9 @@ public class ClassUnloader { public static final String INTERNAL_CLASS_LOADER_NAME = "nsk.share.CustomClassLoader"; /** - * Whole amount of time in milliseconds to wait for class loader to be reclaimed. + * Phantom reference to the class loader. */ - private static final int WAIT_TIMEOUT = 15000; - - /** - * Sleep time in milliseconds for the loop waiting for the class loader to be reclaimed. - */ - private static final int WAIT_DELTA = 1000; - - /** - * Has class loader been reclaimed or not. - */ - volatile boolean is_reclaimed = false; + private PhantomReference customClassLoaderPhantomRef = null; /** * Current class loader used for loading classes. @@ -101,6 +91,14 @@ public class ClassUnloader { */ private Vector> classObjects = new Vector>(); + /** + * Has class loader been reclaimed or not. + */ + private boolean isClassLoaderReclaimed() { + return customClassLoaderPhantomRef != null + && customClassLoaderPhantomRef.refersTo(null); + } + /** * Class object of the first class been loaded with current class loader. * To get the rest loaded classes use getLoadedClass(int). @@ -138,8 +136,7 @@ public class ClassUnloader { customClassLoader = new CustomClassLoader(); classObjects.removeAllElements(); - // Register a Cleaner to inform us when the class loader has been reclaimed. - Cleaner.create().register(customClassLoader, () -> { is_reclaimed = true; } ); + customClassLoaderPhantomRef = new PhantomReference<>(customClassLoader, null); return customClassLoader; } @@ -154,8 +151,7 @@ public class ClassUnloader { this.customClassLoader = customClassLoader; classObjects.removeAllElements(); - // Register a Cleaner to inform us when the class loader has been reclaimed. - Cleaner.create().register(customClassLoader, () -> { is_reclaimed = true; } ); + customClassLoaderPhantomRef = new PhantomReference<>(customClassLoader, null); } /** @@ -244,32 +240,15 @@ public class ClassUnloader { */ public boolean unloadClass(ExecutionController stresser) { - is_reclaimed = false; - // free references to class and class loader to be able for collecting by GC - long waitTimeout = (customClassLoader == null) ? 0 : WAIT_TIMEOUT; classObjects.removeAllElements(); customClassLoader = null; // force class unloading by eating memory pool eatMemory(stresser); - // give GC chance to run and wait for receiving reclaim notification - long timeToFinish = System.currentTimeMillis() + waitTimeout; - while (!is_reclaimed && System.currentTimeMillis() < timeToFinish) { - if (!stresser.continueExecution()) { - return false; - } - try { - // suspend thread for a while - Thread.sleep(WAIT_DELTA); - } catch (InterruptedException e) { - throw new Failure("Unexpected InterruptedException while class unloading: " + e); - } - } - // force GC to unload marked class loader and its classes - if (is_reclaimed) { + if (isClassLoaderReclaimed()) { Runtime.getRuntime().gc(); return true; } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/AbstractDebuggeeTest.java b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/AbstractDebuggeeTest.java index 0668297d211..86d5d7ecd24 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/AbstractDebuggeeTest.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/jpda/AbstractDebuggeeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -149,19 +149,11 @@ public class AbstractDebuggeeTest { } } - public static final int MAX_UNLOAD_ATTEMPS = 5; - public void unloadTestClass(String className, boolean expectedUnloadingResult) { ClassUnloader classUnloader = loadedClasses.get(className); - int unloadAttemps = 0; - if (classUnloader != null) { - boolean wasUnloaded = false; - - while (!wasUnloaded && (unloadAttemps++ < MAX_UNLOAD_ATTEMPS)) { - wasUnloaded = classUnloader.unloadClass(); - } + boolean wasUnloaded = classUnloader.unloadClass(); if (wasUnloaded) loadedClasses.remove(className); From 0a97bef840f8799313a1a55a65d9334e09cc1cf4 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Fri, 17 Oct 2025 09:32:40 +0000 Subject: [PATCH 0262/1639] 8369814: G1: Relax card mark and store ordering Reviewed-by: tschatzl, fandreuzzi --- src/hotspot/share/gc/g1/g1BarrierSet.hpp | 4 - src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 1 - .../gc/parallel/parallelScavengeHeap.cpp | 1 - src/hotspot/share/gc/serial/serialHeap.cpp | 1 - .../share/gc/shared/cardTableBarrierSet.cpp | 73 +------------------ .../share/gc/shared/cardTableBarrierSet.hpp | 28 ------- src/hotspot/share/gc/shared/gc_globals.hpp | 4 - src/hotspot/share/gc/shared/vmStructs_gc.hpp | 1 - .../gc/shenandoah/shenandoahBarrierSet.cpp | 1 - src/hotspot/share/runtime/javaThread.cpp | 4 - src/hotspot/share/runtime/javaThread.hpp | 8 -- 11 files changed, 3 insertions(+), 123 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1BarrierSet.hpp b/src/hotspot/share/gc/g1/g1BarrierSet.hpp index 20642cfc7e6..1e5c111a652 100644 --- a/src/hotspot/share/gc/g1/g1BarrierSet.hpp +++ b/src/hotspot/share/gc/g1/g1BarrierSet.hpp @@ -84,10 +84,6 @@ class G1BarrierSet: public CardTableBarrierSet { // Update the given thread's card table (byte map) base to the current card table's. void update_card_table_base(Thread* thread); - virtual bool card_mark_must_follow_store() const { - return true; - } - // Add "pre_val" to a set of objects that may have been disconnected from the // pre-marking object graph. Prefer the version that takes location, as it // can avoid touching the heap unnecessarily. diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index c1b18a71cfb..485caa9f6c0 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -1391,7 +1391,6 @@ jint G1CollectedHeap::initialize() { G1CardTable* refinement_table = new G1CardTable(_reserved); G1BarrierSet* bs = new G1BarrierSet(card_table, refinement_table); - bs->initialize(); assert(bs->is_a(BarrierSet::G1BarrierSet), "sanity"); // Create space mappers. diff --git a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp index 18cbe2403d8..eb1552e3db6 100644 --- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp +++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp @@ -79,7 +79,6 @@ jint ParallelScavengeHeap::initialize() { card_table->initialize(old_rs.base(), young_rs.base()); CardTableBarrierSet* const barrier_set = new CardTableBarrierSet(card_table); - barrier_set->initialize(); BarrierSet::set_barrier_set(barrier_set); // Set up WorkerThreads diff --git a/src/hotspot/share/gc/serial/serialHeap.cpp b/src/hotspot/share/gc/serial/serialHeap.cpp index 3511318e169..8022b317ca6 100644 --- a/src/hotspot/share/gc/serial/serialHeap.cpp +++ b/src/hotspot/share/gc/serial/serialHeap.cpp @@ -182,7 +182,6 @@ jint SerialHeap::initialize() { _rem_set->initialize(young_rs.base(), old_rs.base()); CardTableBarrierSet *bs = new CardTableBarrierSet(_rem_set); - bs->initialize(); BarrierSet::set_barrier_set(bs); _young_gen = new DefNewGeneration(young_rs, NewSize, MinNewSize, MaxNewSize); diff --git a/src/hotspot/share/gc/shared/cardTableBarrierSet.cpp b/src/hotspot/share/gc/shared/cardTableBarrierSet.cpp index dfa00636dec..de514f64be2 100644 --- a/src/hotspot/share/gc/shared/cardTableBarrierSet.cpp +++ b/src/hotspot/share/gc/shared/cardTableBarrierSet.cpp @@ -57,7 +57,6 @@ CardTableBarrierSet::CardTableBarrierSet(BarrierSetAssembler* barrier_set_assemb barrier_set_c1, barrier_set_c2, fake_rtti.add_tag(BarrierSet::CardTableBarrierSet)), - _defer_initial_card_mark(false), _card_table(card_table) {} @@ -66,14 +65,9 @@ CardTableBarrierSet::CardTableBarrierSet(CardTable* card_table) : make_barrier_set_c1(), make_barrier_set_c2(), BarrierSet::FakeRtti(BarrierSet::CardTableBarrierSet)), - _defer_initial_card_mark(false), _card_table(card_table) {} -void CardTableBarrierSet::initialize() { - initialize_deferred_card_mark_barriers(); -} - CardTableBarrierSet::~CardTableBarrierSet() { delete _card_table; } @@ -108,9 +102,7 @@ void CardTableBarrierSet::print_on(outputStream* st) const { // to the post-barrier, we note that G1 needs a RS update barrier // which simply enqueues a (sequence of) dirty cards which may // optionally be refined by the concurrent update threads. Note -// that this barrier need only be applied to a non-young write, -// but, because of the presence of concurrent refinement, -// must strictly follow the oop-store. +// that this barrier need only be applied to a non-young write. // // For any future collector, this code should be reexamined with // that specific collector in mind, and the documentation above suitably @@ -120,72 +112,13 @@ void CardTableBarrierSet::on_slowpath_allocation_exit(JavaThread* thread, oop ne if (!ReduceInitialCardMarks) { return; } - // If a previous card-mark was deferred, flush it now. - flush_deferred_card_mark_barrier(thread); if (new_obj->is_typeArray() || _card_table->is_in_young(new_obj)) { // Arrays of non-references don't need a post-barrier. - // The deferred_card_mark region should be empty - // following the flush above. - assert(thread->deferred_card_mark().is_empty(), "Error"); } else { MemRegion mr(cast_from_oop(new_obj), new_obj->size()); assert(!mr.is_empty(), "Error"); - if (_defer_initial_card_mark) { - // Defer the card mark - thread->set_deferred_card_mark(mr); - } else { - // Do the card mark - write_region(mr); - } + // Do the card mark + write_region(mr); } #endif // COMPILER2_OR_JVMCI } - -void CardTableBarrierSet::initialize_deferred_card_mark_barriers() { - // Used for ReduceInitialCardMarks (when COMPILER2 or JVMCI is used); - // otherwise remains unused. -#if COMPILER2_OR_JVMCI - _defer_initial_card_mark = CompilerConfig::is_c2_or_jvmci_compiler_enabled() && ReduceInitialCardMarks - && (DeferInitialCardMark || card_mark_must_follow_store()); -#else - assert(_defer_initial_card_mark == false, "Who would set it?"); -#endif -} - -void CardTableBarrierSet::flush_deferred_card_mark_barrier(JavaThread* thread) { -#if COMPILER2_OR_JVMCI - MemRegion deferred = thread->deferred_card_mark(); - if (!deferred.is_empty()) { - assert(_defer_initial_card_mark, "Otherwise should be empty"); - { - // Verify that the storage points to a parsable object in heap - DEBUG_ONLY(oop old_obj = cast_to_oop(deferred.start());) - assert(!_card_table->is_in_young(old_obj), - "Else should have been filtered in on_slowpath_allocation_exit()"); - assert(oopDesc::is_oop(old_obj), "Not an oop"); - assert(deferred.word_size() == old_obj->size(), - "Mismatch: multiple objects?"); - } - write_region(thread, deferred); - // "Clear" the deferred_card_mark field - thread->set_deferred_card_mark(MemRegion()); - } - assert(thread->deferred_card_mark().is_empty(), "invariant"); -#else - assert(!_defer_initial_card_mark, "Should be false"); - assert(thread->deferred_card_mark().is_empty(), "Should be empty"); -#endif -} - -void CardTableBarrierSet::on_thread_detach(Thread* thread) { - // The deferred store barriers must all have been flushed to the - // card-table (or other remembered set structure) before GC starts - // processing the card-table (or other remembered set). - if (thread->is_Java_thread()) { // Only relevant for Java threads. - flush_deferred_card_mark_barrier(JavaThread::cast(thread)); - } -} - -bool CardTableBarrierSet::card_mark_must_follow_store() const { - return false; -} diff --git a/src/hotspot/share/gc/shared/cardTableBarrierSet.hpp b/src/hotspot/share/gc/shared/cardTableBarrierSet.hpp index 13f3e0783a6..e97da234d16 100644 --- a/src/hotspot/share/gc/shared/cardTableBarrierSet.hpp +++ b/src/hotspot/share/gc/shared/cardTableBarrierSet.hpp @@ -47,9 +47,6 @@ class CardTableBarrierSet: public ModRefBarrierSet { protected: typedef CardTable::CardValue CardValue; - // Used in support of ReduceInitialCardMarks; only consulted if COMPILER2 - // or INCLUDE_JVMCI is being used - bool _defer_initial_card_mark; CardTable* _card_table; CardTableBarrierSet(BarrierSetAssembler* barrier_set_assembler, @@ -64,13 +61,10 @@ public: CardTable* card_table() const { return _card_table; } - void initialize(); - void write_region(JavaThread* thread, MemRegion mr) { write_region(mr); } - public: // Record a reference update. Note that these versions are precise! // The scanning code has to handle the fact that the write barrier may be // either precise or imprecise. We make non-virtual inline variants of @@ -80,29 +74,7 @@ public: virtual void write_region(MemRegion mr); - // ReduceInitialCardMarks - void initialize_deferred_card_mark_barriers(); - - // If the CollectedHeap was asked to defer a store barrier above, - // this informs it to flush such a deferred store barrier to the - // remembered set. - void flush_deferred_card_mark_barrier(JavaThread* thread); - - // If a compiler is eliding store barriers for TLAB-allocated objects, - // we will be informed of a slow-path allocation by a call - // to on_slowpath_allocation_exit() below. Such a call precedes the - // initialization of the object itself, and no post-store-barriers will - // be issued. Some heap types require that the barrier strictly follows - // the initializing stores. (This is currently implemented by deferring the - // barrier until the next slow-path allocation or gc-related safepoint.) - // This interface answers whether a particular barrier type needs the card - // mark to be thus strictly sequenced after the stores. - virtual bool card_mark_must_follow_store() const; - virtual void on_slowpath_allocation_exit(JavaThread* thread, oop new_obj); - virtual void on_thread_detach(Thread* thread); - - virtual void make_parsable(JavaThread* thread) { flush_deferred_card_mark_barrier(thread); } virtual void print_on(outputStream* st) const; diff --git a/src/hotspot/share/gc/shared/gc_globals.hpp b/src/hotspot/share/gc/shared/gc_globals.hpp index 0b245026d68..956bffde156 100644 --- a/src/hotspot/share/gc/shared/gc_globals.hpp +++ b/src/hotspot/share/gc/shared/gc_globals.hpp @@ -418,10 +418,6 @@ "dictionary, classloader_data_graph, metaspace, jni_handles, " \ "codecache_oops, resolved_method_table, stringdedup") \ \ - product(bool, DeferInitialCardMark, false, DIAGNOSTIC, \ - "When +ReduceInitialCardMarks, explicitly defer any that " \ - "may arise from new_pre_store_barrier") \ - \ product(bool, UseCondCardMark, false, \ "Check for already marked card before updating card table") \ \ diff --git a/src/hotspot/share/gc/shared/vmStructs_gc.hpp b/src/hotspot/share/gc/shared/vmStructs_gc.hpp index bba9c9e099f..9d84a56fbd7 100644 --- a/src/hotspot/share/gc/shared/vmStructs_gc.hpp +++ b/src/hotspot/share/gc/shared/vmStructs_gc.hpp @@ -88,7 +88,6 @@ nonstatic_field(CardTable, _byte_map_size, const size_t) \ nonstatic_field(CardTable, _byte_map, CardTable::CardValue*) \ nonstatic_field(CardTable, _byte_map_base, CardTable::CardValue*) \ - nonstatic_field(CardTableBarrierSet, _defer_initial_card_mark, bool) \ nonstatic_field(CardTableBarrierSet, _card_table, CardTable*) \ \ static_field(CollectedHeap, _lab_alignment_reserve, size_t) \ diff --git a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp index f6733d4a923..2aa37d7c575 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.cpp @@ -103,7 +103,6 @@ void ShenandoahBarrierSet::on_slowpath_allocation_exit(JavaThread* thread, oop n ); } #endif // COMPILER2_OR_JVMCI - assert(thread->deferred_card_mark().is_empty(), "We don't use this"); } void ShenandoahBarrierSet::on_thread_create(Thread* thread) { diff --git a/src/hotspot/share/runtime/javaThread.cpp b/src/hotspot/share/runtime/javaThread.cpp index 8bb8095878f..36544cf1118 100644 --- a/src/hotspot/share/runtime/javaThread.cpp +++ b/src/hotspot/share/runtime/javaThread.cpp @@ -535,7 +535,6 @@ JavaThread::JavaThread(MemTag mem_tag) : set_requires_cross_modify_fence(false); pd_initialize(); - assert(deferred_card_mark().is_empty(), "Default MemRegion ctor"); } JavaThread* JavaThread::create_attaching_thread() { @@ -1359,9 +1358,6 @@ void JavaThread::pop_jni_handle_block() { } void JavaThread::oops_do_no_frames(OopClosure* f, NMethodClosure* cf) { - // Verify that the deferred card marks have been flushed. - assert(deferred_card_mark().is_empty(), "Should be empty during GC"); - // Traverse the GCHandles Thread::oops_do_no_frames(f, cf); diff --git a/src/hotspot/share/runtime/javaThread.hpp b/src/hotspot/share/runtime/javaThread.hpp index c8be1594a69..a6a00bfbd03 100644 --- a/src/hotspot/share/runtime/javaThread.hpp +++ b/src/hotspot/share/runtime/javaThread.hpp @@ -149,11 +149,6 @@ class JavaThread: public Thread { oop _vm_result_oop; // oop result is GC-preserved Metadata* _vm_result_metadata; // non-oop result - // See ReduceInitialCardMarks: this holds the precise space interval of - // the most recent slow path allocation for which compiled code has - // elided card-marks for performance along the fast-path. - MemRegion _deferred_card_mark; - ObjectMonitor* volatile _current_pending_monitor; // ObjectMonitor this thread is waiting to lock bool _current_pending_monitor_is_from_java; // locking is from Java code ObjectMonitor* volatile _current_waiting_monitor; // ObjectMonitor on which this thread called Object.wait() @@ -776,9 +771,6 @@ public: void set_vm_result_metadata(Metadata* x) { _vm_result_metadata = x; } - MemRegion deferred_card_mark() const { return _deferred_card_mark; } - void set_deferred_card_mark(MemRegion mr) { _deferred_card_mark = mr; } - // Is thread in scope of an InternalOOMEMark? bool is_in_internal_oome_mark() const { return _is_in_internal_oome_mark; } void set_is_in_internal_oome_mark(bool b) { _is_in_internal_oome_mark = b; } From e8e2aadd9ea302b7b448d0fda9d069d3813f31c5 Mon Sep 17 00:00:00 2001 From: Hamlin Li Date: Fri, 17 Oct 2025 11:22:23 +0000 Subject: [PATCH 0263/1639] 8369685: RISC-V: refactor code related to RVFeatureValue::enabled Reviewed-by: fyang, rehn --- src/hotspot/cpu/riscv/vm_version_riscv.cpp | 13 +----- src/hotspot/cpu/riscv/vm_version_riscv.hpp | 45 +++++++++---------- .../linux_riscv/vm_version_linux_riscv.cpp | 13 ++++-- 3 files changed, 31 insertions(+), 40 deletions(-) diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.cpp b/src/hotspot/cpu/riscv/vm_version_riscv.cpp index 9d6146a8389..6f4babc872f 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.cpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.cpp @@ -103,17 +103,6 @@ void VM_Version::common_initialize() { useRVA23U64Profile(); } - // Enable vendor specific features - - if (mvendorid.enabled()) { - // Rivos - if (mvendorid.value() == RIVOS) { - if (FLAG_IS_DEFAULT(UseConservativeFence)) { - FLAG_SET_DEFAULT(UseConservativeFence, false); - } - } - } - if (UseZic64b) { if (CacheLineSize != 64) { assert(!FLAG_IS_DEFAULT(CacheLineSize), "default cache line size should be 64 bytes"); @@ -199,7 +188,7 @@ void VM_Version::common_initialize() { FLAG_SET_DEFAULT(UsePopCountInstruction, false); } - if (UseZicboz && zicboz_block_size.enabled() && zicboz_block_size.value() > 0) { + if (UseZicboz && zicboz_block_size.value() > 0) { assert(is_power_of_2(zicboz_block_size.value()), "Sanity"); if (FLAG_IS_DEFAULT(UseBlockZeroing)) { FLAG_SET_DEFAULT(UseBlockZeroing, true); diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.hpp b/src/hotspot/cpu/riscv/vm_version_riscv.hpp index 3d555d47e9f..f74992cbc37 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.hpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.hpp @@ -52,24 +52,19 @@ class VM_Version : public Abstract_VM_Version { const char* const _pretty; const bool _feature_string; const uint64_t _linux_feature_bit; - int64_t _value; + public: RVFeatureValue(const char* pretty, int linux_bit_num, bool fstring) : - _pretty(pretty), _feature_string(fstring), _linux_feature_bit(nth_bit(linux_bit_num)), - _value(-1) { + _pretty(pretty), _feature_string(fstring), _linux_feature_bit(nth_bit(linux_bit_num)) { } - virtual void enable_feature(int64_t value = 0) { - _value = value; - } - virtual void disable_feature() { - _value = -1; - } - const char* pretty() { return _pretty; } - uint64_t feature_bit() { return _linux_feature_bit; } - bool feature_string() { return _feature_string; } - int64_t value() { return _value; } + virtual void enable_feature(int64_t value = 0) = 0; + virtual void disable_feature() = 0; + const char* pretty() { return _pretty; } + uint64_t feature_bit() { return _linux_feature_bit; } + bool feature_string() { return _feature_string; } virtual bool enabled() = 0; virtual void update_flag() = 0; + virtual void log_enabled() = 0; }; #define UPDATE_DEFAULT(flag) \ @@ -135,13 +130,12 @@ class VM_Version : public Abstract_VM_Version { return RVExtFeatures::current()->support_feature(_cpu_feature_index); } void enable_feature(int64_t value = 0) { - RVFeatureValue::enable_feature(value); RVExtFeatures::current()->set_feature(_cpu_feature_index); } void disable_feature() { - RVFeatureValue::disable_feature(); RVExtFeatures::current()->clear_feature(_cpu_feature_index); } + void log_enabled(); protected: bool deps_all_enabled(RVExtFeatureValue* dep0, ...) { @@ -196,21 +190,22 @@ class VM_Version : public Abstract_VM_Version { }; class RVNonExtFeatureValue : public RVFeatureValue { - bool _enabled; + static const int64_t DEFAULT_VALUE = -1; + int64_t _value; + public: RVNonExtFeatureValue(const char* pretty, int linux_bit_num, bool fstring) : RVFeatureValue(pretty, linux_bit_num, fstring), - _enabled(false) { + _value(DEFAULT_VALUE) { } - bool enabled() { return _enabled; } - void enable_feature(int64_t value = 0) { - RVFeatureValue::enable_feature(value); - _enabled = true; - } - void disable_feature() { - RVFeatureValue::disable_feature(); - _enabled = false; + bool enabled() { return _value != DEFAULT_VALUE; } + void enable_feature(int64_t value) { + assert(value != DEFAULT_VALUE, "Sanity"); + _value = value; } + void disable_feature() { _value = DEFAULT_VALUE; } + int64_t value() { return _value; } + void log_enabled(); }; public: diff --git a/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp b/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp index e414a3889c2..0799de014a9 100644 --- a/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp +++ b/src/hotspot/os_cpu/linux_riscv/vm_version_linux_riscv.cpp @@ -103,6 +103,14 @@ uint32_t VM_Version::cpu_vector_length() { return (uint32_t)read_csr(CSR_VLENB); } +void VM_Version::RVExtFeatureValue::log_enabled() { + log_debug(os, cpu)("Enabled RV64 feature \"%s\"", pretty()); +} + +void VM_Version::RVNonExtFeatureValue::log_enabled() { + log_debug(os, cpu)("Enabled RV64 feature \"%s\" (%ld)", pretty(), value()); +} + void VM_Version::setup_cpu_available_features() { assert(ext_i.feature_bit() == HWCAP_ISA_I, "Bit for I must follow Linux HWCAP"); @@ -144,9 +152,8 @@ void VM_Version::setup_cpu_available_features() { continue; } - log_debug(os, cpu)("Enabled RV64 feature \"%s\" (%ld)", - _feature_list[i]->pretty(), - _feature_list[i]->value()); + _feature_list[i]->log_enabled(); + // The feature string if (_feature_list[i]->feature_string()) { const char* tmp = _feature_list[i]->pretty(); From b159ca097a71407d0bc10f6c5d86d5f45c7d7642 Mon Sep 17 00:00:00 2001 From: Francesco Andreuzzi Date: Fri, 17 Oct 2025 14:19:21 +0000 Subject: [PATCH 0264/1639] 8369980: Use ThreadsClaimTokenScope in ShenandoahThreadRoots Reviewed-by: ayang, wkemper --- .../share/gc/shenandoah/shenandoahRootProcessor.cpp | 10 +++------- .../share/gc/shenandoah/shenandoahRootProcessor.hpp | 5 +++-- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp index a56113868be..9e6b1960708 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.cpp @@ -58,9 +58,9 @@ void ShenandoahJavaThreadsIterator::threads_do(ThreadClosure* cl, uint worker_id } ShenandoahThreadRoots::ShenandoahThreadRoots(ShenandoahPhaseTimings::Phase phase, bool is_par) : - _phase(phase), _is_par(is_par) { - Threads::change_thread_claim_token(); -} + _phase(phase), + _is_par(is_par), + _threads_claim_token_scope() {} void ShenandoahThreadRoots::oops_do(OopClosure* oops_cl, NMethodClosure* code_cl, uint worker_id) { ShenandoahWorkerTimingsTracker timer(_phase, ShenandoahPhaseTimings::ThreadRoots, worker_id); @@ -74,10 +74,6 @@ void ShenandoahThreadRoots::threads_do(ThreadClosure* tc, uint worker_id) { Threads::possibly_parallel_threads_do(_is_par, tc); } -ShenandoahThreadRoots::~ShenandoahThreadRoots() { - Threads::assert_all_threads_claimed(); -} - ShenandoahCodeCacheRoots::ShenandoahCodeCacheRoots(ShenandoahPhaseTimings::Phase phase) : _phase(phase) { } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp index 40d4077256d..29d8c9fac2d 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahRootProcessor.hpp @@ -33,6 +33,7 @@ #include "gc/shenandoah/shenandoahSharedVariables.hpp" #include "gc/shenandoah/shenandoahUtils.hpp" #include "memory/iterator.hpp" +#include "runtime/threads.hpp" template class ShenandoahVMWeakRoots { @@ -87,10 +88,10 @@ public: class ShenandoahThreadRoots { private: ShenandoahPhaseTimings::Phase _phase; - const bool _is_par; + const bool _is_par; + ThreadsClaimTokenScope _threads_claim_token_scope; public: ShenandoahThreadRoots(ShenandoahPhaseTimings::Phase phase, bool is_par); - ~ShenandoahThreadRoots(); void oops_do(OopClosure* oops_cl, NMethodClosure* code_cl, uint worker_id); void threads_do(ThreadClosure* tc, uint worker_id); From cc6f8f1307476886aa3c43a2b966fc7bff2be04e Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Fri, 17 Oct 2025 15:12:27 +0000 Subject: [PATCH 0265/1639] 8369997: Tests that use custom scheduler should use jdk.test.lib.thread.VThreadScheduler Reviewed-by: sspitsyn, alanb --- .../ThreadStateTest/ThreadStateTest.java | 30 +++++-------------- .../WriteToReleasesCarrier.java | 19 ++++-------- .../TestTerminatingThreadLocal.java | 27 +++-------------- 3 files changed, 16 insertions(+), 60 deletions(-) diff --git a/test/hotspot/jtreg/serviceability/jvmti/vthread/ThreadStateTest/ThreadStateTest.java b/test/hotspot/jtreg/serviceability/jvmti/vthread/ThreadStateTest/ThreadStateTest.java index 4c8b9bb030f..c6a7debed1a 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/vthread/ThreadStateTest/ThreadStateTest.java +++ b/test/hotspot/jtreg/serviceability/jvmti/vthread/ThreadStateTest/ThreadStateTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,15 +27,17 @@ * @summary Exercise JvmtiThreadState creation concurrently with terminating vthreads * @requires vm.continuations * @modules java.base/java.lang:+open + * @library /test/lib * @run main/othervm/native -agentlib:ThreadStateTest ThreadStateTest */ -import java.util.concurrent.*; import java.util.Arrays; import java.util.ArrayList; import java.util.List; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.ThreadFactory; +import jdk.test.lib.thread.VThreadScheduler; public class ThreadStateTest { static final int VTHREAD_COUNT = 64; @@ -59,7 +61,7 @@ public class ThreadStateTest { while (tryCount-- > 0) { ExecutorService scheduler = Executors.newFixedThreadPool(8); - ThreadFactory factory = virtualThreadBuilder(scheduler).factory(); + ThreadFactory factory = VThreadScheduler.virtualThreadBuilder(scheduler).factory(); List virtualThreads = new ArrayList<>(); for (int i = 0; i < VTHREAD_COUNT; i++) { @@ -98,22 +100,4 @@ public class ThreadStateTest { ThreadStateTest obj = new ThreadStateTest(); obj.runTest(); } - - private static Thread.Builder.OfVirtual virtualThreadBuilder(Executor scheduler) { - Thread.Builder.OfVirtual builder = Thread.ofVirtual(); - try { - Class clazz = Class.forName("java.lang.ThreadBuilders$VirtualThreadBuilder"); - Constructor ctor = clazz.getDeclaredConstructor(Executor.class); - ctor.setAccessible(true); - return (Thread.Builder.OfVirtual) ctor.newInstance(scheduler); - } catch (InvocationTargetException e) { - Throwable cause = e.getCause(); - if (cause instanceof RuntimeException re) { - throw re; - } - throw new RuntimeException(e); - } catch (Exception e) { - throw new RuntimeException(e); - } - } } diff --git a/test/jdk/java/io/ByteArrayOutputStream/WriteToReleasesCarrier.java b/test/jdk/java/io/ByteArrayOutputStream/WriteToReleasesCarrier.java index c0607fd9494..a0c13f24c7c 100644 --- a/test/jdk/java/io/ByteArrayOutputStream/WriteToReleasesCarrier.java +++ b/test/jdk/java/io/ByteArrayOutputStream/WriteToReleasesCarrier.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ * @summary Test ByteArrayOutputStream.writeTo releases carrier thread * @requires vm.continuations * @modules java.base/java.lang:+open + * @library /test/lib * @run main WriteToReleasesCarrier */ @@ -34,14 +35,14 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.nio.charset.StandardCharsets; -import java.lang.reflect.Constructor; import java.util.Arrays; import java.util.concurrent.CountDownLatch; -import java.util.concurrent.ExecutorService; import java.util.concurrent.Executor; import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.locks.LockSupport; +import jdk.test.lib.thread.VThreadScheduler; public class WriteToReleasesCarrier { public static void main(String[] args) throws Exception { @@ -53,7 +54,7 @@ public class WriteToReleasesCarrier { var target = new ParkingOutputStream(); try (ExecutorService scheduler = Executors.newFixedThreadPool(1)) { - Thread.Builder builder = virtualThreadBuilder(scheduler); + Thread.Builder builder = VThreadScheduler.virtualThreadBuilder(scheduler); var started = new CountDownLatch(1); var vthread1 = builder.start(() -> { started.countDown(); @@ -118,14 +119,4 @@ public class WriteToReleasesCarrier { return baos.toByteArray(); } } - - /** - * Returns a builder to create virtual threads that use the given scheduler. - */ - static Thread.Builder.OfVirtual virtualThreadBuilder(Executor scheduler) throws Exception { - Class clazz = Class.forName("java.lang.ThreadBuilders$VirtualThreadBuilder"); - Constructor ctor = clazz.getDeclaredConstructor(Executor.class); - ctor.setAccessible(true); - return (Thread.Builder.OfVirtual) ctor.newInstance(scheduler); - } } diff --git a/test/jdk/jdk/internal/misc/TerminatingThreadLocal/TestTerminatingThreadLocal.java b/test/jdk/jdk/internal/misc/TerminatingThreadLocal/TestTerminatingThreadLocal.java index cf46c5b1d22..bbf2e99b950 100644 --- a/test/jdk/jdk/internal/misc/TerminatingThreadLocal/TestTerminatingThreadLocal.java +++ b/test/jdk/jdk/internal/misc/TerminatingThreadLocal/TestTerminatingThreadLocal.java @@ -23,9 +23,7 @@ import jdk.internal.misc.TerminatingThreadLocal; -import java.lang.reflect.Constructor; import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; import java.util.Arrays; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; @@ -37,6 +35,8 @@ import java.util.function.Consumer; import java.util.function.Function; import java.util.stream.Stream; +import jdk.test.lib.thread.VThreadScheduler; + import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import static org.testng.Assert.*; @@ -46,6 +46,7 @@ import static org.testng.Assert.*; * @bug 8202788 8291897 8357637 * @summary TerminatingThreadLocal unit test * @modules java.base/java.lang:+open java.base/jdk.internal.misc + * @library /test/lib * @requires vm.continuations * @run testng/othervm TestTerminatingThreadLocal */ @@ -139,7 +140,7 @@ public class TestTerminatingThreadLocal { // capture carrier Thread carrier = pool.submit(Thread::currentThread).get(); - ThreadFactory factory = virtualThreadBuilder(pool) + ThreadFactory factory = VThreadScheduler.virtualThreadBuilder(pool) .name("ttl-test-virtual-", 0) .factory(); try (var executor = Executors.newThreadPerTaskExecutor(factory)) { @@ -202,24 +203,4 @@ public class TestTerminatingThreadLocal { assertEquals(terminatedValues, List.of(ttlValue)); } - - /** - * Returns a builder to create virtual threads that use the given scheduler. - */ - static Thread.Builder.OfVirtual virtualThreadBuilder(Executor scheduler) { - try { - Class clazz = Class.forName("java.lang.ThreadBuilders$VirtualThreadBuilder"); - Constructor ctor = clazz.getDeclaredConstructor(Executor.class); - ctor.setAccessible(true); - return (Thread.Builder.OfVirtual) ctor.newInstance(scheduler); - } catch (InvocationTargetException e) { - Throwable cause = e.getCause(); - if (cause instanceof RuntimeException re) { - throw re; - } - throw new RuntimeException(e); - } catch (Exception e) { - throw new RuntimeException(e); - } - } } From 28bf9176b8d460242bb7cedfb3bde5c6294c56fb Mon Sep 17 00:00:00 2001 From: Leonid Mesnik Date: Fri, 17 Oct 2025 16:03:24 +0000 Subject: [PATCH 0266/1639] 8348844: Remove remaining JVMTI tests from ProblemList-Virtual, use requires instead Reviewed-by: dholmes, alanb, syan, sspitsyn --- test/hotspot/jtreg/ProblemList-Virtual.txt | 16 -------------- .../arguments/TestNewSizeThreadIncrease.java | 3 ++- .../gc/g1/TestSkipRebuildRemsetPhase.java | 3 ++- .../MachCodeFramesInErrorFile.java | 3 ++- .../Thread/AsyncExceptionOnMonitorEnter.java | 1 + .../jtreg/runtime/Thread/StopAtExit.java | 3 ++- .../handshake/HandshakeWalkStackTest.java | 3 ++- .../curthrcputime001/TestDescription.java | 3 ++- .../thrcputime001/TestDescription.java | 3 ++- test/jdk/ProblemList-Virtual.txt | 21 ------------------- .../java/lang/StackWalker/CallerFromMain.java | 5 +++-- .../java/lang/StackWalker/DumpStackTest.java | 3 ++- .../java/lang/StackWalker/StackWalkTest.java | 3 ++- test/jdk/java/lang/Thread/MainThreadTest.java | 3 ++- .../lang/Thread/UncaughtExceptionsTest.java | 3 ++- .../java/lang/ref/OOMEInReferenceHandler.java | 3 ++- .../util/concurrent/locks/Lock/OOMEInAQS.java | 3 ++- .../jdk/internal/vm/Continuation/Scoped.java | 3 ++- 18 files changed, 32 insertions(+), 53 deletions(-) diff --git a/test/hotspot/jtreg/ProblemList-Virtual.txt b/test/hotspot/jtreg/ProblemList-Virtual.txt index 3c74d7bf816..31684662194 100644 --- a/test/hotspot/jtreg/ProblemList-Virtual.txt +++ b/test/hotspot/jtreg/ProblemList-Virtual.txt @@ -33,11 +33,6 @@ vmTestbase/vm/mlvm/indy/func/jvmti/mergeCP_indy2manyDiff_a/TestDescription.java vmTestbase/nsk/jvmti/CompiledMethodUnload/compmethunload001/TestDescription.java 8300711 generic-all -#### -## Tests for functionality which currently is not supported for virtual threads - -vmTestbase/nsk/jvmti/GetCurrentThreadCpuTime/curthrcputime001/TestDescription.java 8348844 generic-all -vmTestbase/nsk/jvmti/GetThreadCpuTime/thrcputime001/TestDescription.java 8348844 generic-all #### ## Test fails because it expects to find vthreads in GetAllThreads @@ -82,14 +77,3 @@ vmTestbase/nsk/jdi/VMOutOfMemoryException/VMOutOfMemoryException001/VMOutOfMemor # to make progress when all other threads are currently suspended. vmTestbase/nsk/jdi/ThreadReference/isSuspended/issuspended002/TestDescription.java 8338713 generic-all -########## -## Tests incompatible with with virtual test thread factory. -## There is no goal to run all test with virtual test thread factory. -## So any test migth be added as incompatible, the bug is not required. - -gc/arguments/TestNewSizeThreadIncrease.java 0000000 generic-all -gc/g1/TestSkipRebuildRemsetPhase.java 0000000 generic-all -runtime/ErrorHandling/MachCodeFramesInErrorFile.java 0000000 generic-all -runtime/Thread/AsyncExceptionOnMonitorEnter.java 0000000 generic-all -runtime/Thread/StopAtExit.java 0000000 generic-all -runtime/handshake/HandshakeWalkStackTest.java 0000000 generic-all diff --git a/test/hotspot/jtreg/gc/arguments/TestNewSizeThreadIncrease.java b/test/hotspot/jtreg/gc/arguments/TestNewSizeThreadIncrease.java index efe703f9295..f885ef7e462 100644 --- a/test/hotspot/jtreg/gc/arguments/TestNewSizeThreadIncrease.java +++ b/test/hotspot/jtreg/gc/arguments/TestNewSizeThreadIncrease.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ package gc.arguments; * @library /test/lib * @library / * @requires vm.gc.Serial + * @requires test.thread.factory == null * @modules java.base/jdk.internal.misc * java.management * @run driver gc.arguments.TestNewSizeThreadIncrease diff --git a/test/hotspot/jtreg/gc/g1/TestSkipRebuildRemsetPhase.java b/test/hotspot/jtreg/gc/g1/TestSkipRebuildRemsetPhase.java index d973e897fe1..28524869edb 100644 --- a/test/hotspot/jtreg/gc/g1/TestSkipRebuildRemsetPhase.java +++ b/test/hotspot/jtreg/gc/g1/TestSkipRebuildRemsetPhase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ package gc.g1; * Fill up a region to above the set G1MixedGCLiveThresholdPercent. * @requires vm.gc.G1 * @library /test/lib + * @requires test.thread.factory == null * @build jdk.test.whitebox.WhiteBox * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox * @run driver gc.g1.TestSkipRebuildRemsetPhase diff --git a/test/hotspot/jtreg/runtime/ErrorHandling/MachCodeFramesInErrorFile.java b/test/hotspot/jtreg/runtime/ErrorHandling/MachCodeFramesInErrorFile.java index 5717a576e65..74cedae5f1a 100644 --- a/test/hotspot/jtreg/runtime/ErrorHandling/MachCodeFramesInErrorFile.java +++ b/test/hotspot/jtreg/runtime/ErrorHandling/MachCodeFramesInErrorFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ * @bug 8272586 * @requires vm.flagless * @requires vm.compiler2.enabled + * @requires test.thread.factory == null * @summary Test that abstract machine code is dumped for the top frames in a hs-err log * @library /test/lib * @modules java.base/jdk.internal.misc diff --git a/test/hotspot/jtreg/runtime/Thread/AsyncExceptionOnMonitorEnter.java b/test/hotspot/jtreg/runtime/Thread/AsyncExceptionOnMonitorEnter.java index 8446ffb20fe..a4aa0fe3797 100644 --- a/test/hotspot/jtreg/runtime/Thread/AsyncExceptionOnMonitorEnter.java +++ b/test/hotspot/jtreg/runtime/Thread/AsyncExceptionOnMonitorEnter.java @@ -25,6 +25,7 @@ * @test * @bug 8283044 * @summary Stress delivery of asynchronous exceptions while target is at monitorenter + * @requires test.thread.factory == null * @library /test/hotspot/jtreg/testlibrary * @run main/othervm/native AsyncExceptionOnMonitorEnter 0 * @run main/othervm/native -agentlib:AsyncExceptionOnMonitorEnter AsyncExceptionOnMonitorEnter 1 diff --git a/test/hotspot/jtreg/runtime/Thread/StopAtExit.java b/test/hotspot/jtreg/runtime/Thread/StopAtExit.java index 3ceb955609b..68523c2c189 100644 --- a/test/hotspot/jtreg/runtime/Thread/StopAtExit.java +++ b/test/hotspot/jtreg/runtime/Thread/StopAtExit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 8167108 8266130 8283467 8284632 8286830 * @summary Stress test JVM/TI StopThread() at thread exit. + * @requires test.thread.factory == null * @requires vm.jvmti * @run main/othervm/native -agentlib:StopAtExit StopAtExit */ diff --git a/test/hotspot/jtreg/runtime/handshake/HandshakeWalkStackTest.java b/test/hotspot/jtreg/runtime/handshake/HandshakeWalkStackTest.java index 701e1ec6ec1..6644d14dbc8 100644 --- a/test/hotspot/jtreg/runtime/handshake/HandshakeWalkStackTest.java +++ b/test/hotspot/jtreg/runtime/handshake/HandshakeWalkStackTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ /* * @test HandshakeWalkStackTest + * @requires test.thread.factory == null * @library /testlibrary /test/lib * @build HandshakeWalkStackTest * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetCurrentThreadCpuTime/curthrcputime001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetCurrentThreadCpuTime/curthrcputime001/TestDescription.java index 0b7e1d2a89e..ba09ff735d8 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetCurrentThreadCpuTime/curthrcputime001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetCurrentThreadCpuTime/curthrcputime001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,6 +71,7 @@ * COMMENTS * Fixed the 4968019, 5006885 bugs. * + * @requires test.thread.factory == null * @library /vmTestbase * /test/lib * @build nsk.jvmti.GetCurrentThreadCpuTime.curthrcputime001 diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetThreadCpuTime/thrcputime001/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetThreadCpuTime/thrcputime001/TestDescription.java index cf0fe3e5d2d..b935639e183 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetThreadCpuTime/thrcputime001/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jvmti/GetThreadCpuTime/thrcputime001/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,6 +71,7 @@ * COMMENTS * Fixed the 4968019, 5006885 bugs. * + * @requires test.thread.factory == null * @library /vmTestbase * /test/lib * @build nsk.jvmti.GetThreadCpuTime.thrcputime001 diff --git a/test/jdk/ProblemList-Virtual.txt b/test/jdk/ProblemList-Virtual.txt index dcd4dbac310..dffbd4a952e 100644 --- a/test/jdk/ProblemList-Virtual.txt +++ b/test/jdk/ProblemList-Virtual.txt @@ -38,24 +38,3 @@ javax/management/remote/mandatory/connection/DeadLockTest.java 8309069 windows-x javax/management/remote/mandatory/connection/ConnectionTest.java 8308352 windows-x64 -########## -## Tests incompatible with virtual test thread factory. -## There is no goal to run all test with virtual test thread factory. -## So any test might be added as incompatible, the bug id is not required. - -# Incorrect stack/threadgroup/exception expectations for main thread -java/lang/StackWalker/DumpStackTest.java 0000000 generic-all -java/lang/StackWalker/StackWalkTest.java 0000000 generic-all -java/lang/StackWalker/CallerFromMain.java 0000000 generic-all -java/lang/Thread/MainThreadTest.java 0000000 generic-all -java/lang/Thread/UncaughtExceptionsTest.java 0000000 generic-all -java/lang/invoke/condy/CondyNestedResolutionTest.java 0000000 generic-all -java/lang/ref/OOMEInReferenceHandler.java 0000000 generic-all -java/util/concurrent/locks/Lock/OOMEInAQS.java 0000000 generic-all -jdk/internal/vm/Continuation/Scoped.java 0000000 generic-all - -# The problems with permissions -jdk/jfr/startupargs/TestDumpOnExit.java 0000000 generic-all -java/util/Properties/StoreReproducibilityTest.java 0000000 generic-all -javax/management/ImplementationVersion/ImplVersionTest.java 0000000 generic-all -javax/management/remote/mandatory/version/ImplVersionTest.java 0000000 generic-all diff --git a/test/jdk/java/lang/StackWalker/CallerFromMain.java b/test/jdk/java/lang/StackWalker/CallerFromMain.java index 86e7cfb7043..81456b02c36 100644 --- a/test/jdk/java/lang/StackWalker/CallerFromMain.java +++ b/test/jdk/java/lang/StackWalker/CallerFromMain.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,8 +24,9 @@ /* * @test * @bug 8140450 - * @library /test/lib * @summary Test if the getCallerClass method returns empty optional + * @requires test.thread.factory == null + * @library /test/lib * @run main CallerFromMain exec */ diff --git a/test/jdk/java/lang/StackWalker/DumpStackTest.java b/test/jdk/java/lang/StackWalker/DumpStackTest.java index c196b1c4ad3..1365e39ccfa 100644 --- a/test/jdk/java/lang/StackWalker/DumpStackTest.java +++ b/test/jdk/java/lang/StackWalker/DumpStackTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ * @summary Verify outputs of Thread.dumpStack() and Throwable.printStackTrace(). * This test should also been run against jdk9 successfully except of * VM option MemberNameInStackFrame. + * @requires test.thread.factory == null * @run main/othervm DumpStackTest */ diff --git a/test/jdk/java/lang/StackWalker/StackWalkTest.java b/test/jdk/java/lang/StackWalker/StackWalkTest.java index 80e934d477c..8848f323cab 100644 --- a/test/jdk/java/lang/StackWalker/StackWalkTest.java +++ b/test/jdk/java/lang/StackWalker/StackWalkTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,7 @@ import jdk.test.lib.RandomFactory; * @test * @bug 8140450 * @summary Stack Walk Test (use -Dseed=X to set PRNG seed) + * @requires test.thread.factory == null * @library /test/lib * @build jdk.test.lib.RandomFactory * @compile StackRecorderUtil.java diff --git a/test/jdk/java/lang/Thread/MainThreadTest.java b/test/jdk/java/lang/Thread/MainThreadTest.java index 2482a8aa6d2..7129170ad4e 100644 --- a/test/jdk/java/lang/Thread/MainThreadTest.java +++ b/test/jdk/java/lang/Thread/MainThreadTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 4533087 * @summary Test to see if the main thread is in its thread group + * @requires test.thread.factory == null */ public class MainThreadTest { diff --git a/test/jdk/java/lang/Thread/UncaughtExceptionsTest.java b/test/jdk/java/lang/Thread/UncaughtExceptionsTest.java index 915d1cb6b76..1bb810d372f 100644 --- a/test/jdk/java/lang/Thread/UncaughtExceptionsTest.java +++ b/test/jdk/java/lang/Thread/UncaughtExceptionsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,6 +36,7 @@ import org.junit.jupiter.params.provider.MethodSource; * @bug 4833089 4992454 * @summary Check for proper handling of uncaught exceptions * @author Martin Buchholz + * @requires test.thread.factory == null * @library /test/lib * @build jdk.test.lib.process.* * @run junit UncaughtExceptionsTest diff --git a/test/jdk/java/lang/ref/OOMEInReferenceHandler.java b/test/jdk/java/lang/ref/OOMEInReferenceHandler.java index 2f80fa6178a..9f0a4ea378e 100644 --- a/test/jdk/java/lang/ref/OOMEInReferenceHandler.java +++ b/test/jdk/java/lang/ref/OOMEInReferenceHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @bug 7038914 8016341 * @summary Verify that the reference handler does not die after an OOME allocating the InterruptedException object + * @requires test.thread.factory == null * @run main/othervm -XX:-UseGCOverheadLimit -Xmx24M -XX:-UseTLAB OOMEInReferenceHandler * @author peter.levart@gmail.com * @key intermittent diff --git a/test/jdk/java/util/concurrent/locks/Lock/OOMEInAQS.java b/test/jdk/java/util/concurrent/locks/Lock/OOMEInAQS.java index aee6c3617c8..0ed76f4b885 100644 --- a/test/jdk/java/util/concurrent/locks/Lock/OOMEInAQS.java +++ b/test/jdk/java/util/concurrent/locks/Lock/OOMEInAQS.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,7 @@ import java.util.stream.Stream; * @bug 8066859 * @summary Check that AQS-based locks, conditions, and CountDownLatches do not fail when encountering OOME * @requires vm.gc.G1 + * @requires test.thread.factory == null * @requires !(vm.graal.enabled & vm.compMode == "Xcomp") * @run main/othervm -XX:+UseG1GC -XX:-UseGCOverheadLimit -Xmx48M -XX:-UseTLAB OOMEInAQS */ diff --git a/test/jdk/jdk/internal/vm/Continuation/Scoped.java b/test/jdk/jdk/internal/vm/Continuation/Scoped.java index 908267792b8..448c2ab71a5 100644 --- a/test/jdk/jdk/internal/vm/Continuation/Scoped.java +++ b/test/jdk/jdk/internal/vm/Continuation/Scoped.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ * @test * @summary Nested continuations test * @requires vm.continuations + * @requires test.thread.factory == null * @modules java.base/jdk.internal.vm * @build java.base/java.lang.StackWalkerHelper * @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:+ShowHiddenFrames -Xint Scoped From 1e5e17a10a001c189f6ab19f61efca2d08cb0301 Mon Sep 17 00:00:00 2001 From: Justin Lu Date: Fri, 17 Oct 2025 16:19:35 +0000 Subject: [PATCH 0267/1639] 8369590: LocaleEnhanceTest has incorrectly passing test case Reviewed-by: naoto --- .../java/util/Locale/LocaleEnhanceTest.java | 1077 ++++++++--------- 1 file changed, 482 insertions(+), 595 deletions(-) diff --git a/test/jdk/java/util/Locale/LocaleEnhanceTest.java b/test/jdk/java/util/Locale/LocaleEnhanceTest.java index 7ab8db4c9e2..8bcbe20d197 100644 --- a/test/jdk/java/util/Locale/LocaleEnhanceTest.java +++ b/test/jdk/java/util/Locale/LocaleEnhanceTest.java @@ -31,9 +31,8 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.net.URISyntaxException; import java.net.URL; +import java.nio.charset.StandardCharsets; import java.text.DecimalFormatSymbols; -import java.util.ArrayList; -import java.util.Arrays; import java.util.Calendar; import java.util.IllformedLocaleException; import java.util.List; @@ -47,26 +46,24 @@ import org.junit.jupiter.params.provider.EmptySource; import org.junit.jupiter.params.provider.NullSource; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; -/** +/* * @test * @bug 6875847 6992272 7002320 7015500 7023613 7032820 7033504 7004603 * 7044019 8008577 8176853 8255086 8263202 8287868 8174269 8369452 + * 8369590 * @summary test API changes to Locale * @modules jdk.localedata - * @compile LocaleEnhanceTest.java * @run junit/othervm -esa LocaleEnhanceTest */ public class LocaleEnhanceTest { - public LocaleEnhanceTest() { - } - - /// - /// Generic sanity tests - /// - /** A canonical language code. */ private static final String l = "en"; @@ -79,6 +76,10 @@ public class LocaleEnhanceTest { /** A canonical variant code. */ private static final String v = "NewYork"; + /// + /// Generic sanity tests + /// + /** * Ensure that Builder builds locales that have the expected * tag and java6 ID. Note the odd cases for the ID. @@ -124,12 +125,12 @@ public class LocaleEnhanceTest { .setRegion(idc) .setVariant(idv) .build(); - assertEquals(msg + "language", idl, l.getLanguage()); - assertEquals(msg + "script", ids, l.getScript()); - assertEquals(msg + "country", idc, l.getCountry()); - assertEquals(msg + "variant", idv, l.getVariant()); - assertEquals(msg + "tag", tag, l.toLanguageTag()); - assertEquals(msg + "id", id, l.toString()); + assertEquals(idl, l.getLanguage(), msg + "language"); + assertEquals(ids, l.getScript(), msg + "script"); + assertEquals(idc, l.getCountry(), msg + "country"); + assertEquals(idv, l.getVariant(), msg + "variant"); + assertEquals(tag, l.toLanguageTag(), msg + "tag"); + assertEquals(id, l.toString(), msg + "id"); } catch (IllegalArgumentException e) { fail(msg + e.getMessage()); @@ -181,13 +182,13 @@ public class LocaleEnhanceTest { .setVariant(idv) .build(); - assertEquals(msg + " language", idl, l.getLanguage()); - assertEquals(msg + " script", ids, l.getScript()); - assertEquals(msg + " country", idc, l.getCountry()); - assertEquals(msg + " variant", idv, l.getVariant()); + assertEquals(idl, l.getLanguage(), msg + " language"); + assertEquals(ids, l.getScript(), msg + " script"); + assertEquals(idc, l.getCountry(), msg + " country"); + assertEquals(idv, l.getVariant(), msg + " variant"); - assertEquals(msg + "tag", tag, l.toLanguageTag()); - assertEquals(msg + "id", id, l.toString()); + assertEquals(tag, l.toLanguageTag(), msg + "tag"); + assertEquals(id, l.toString(), msg + "id"); } catch (IllegalArgumentException e) { fail(msg + e.getMessage()); @@ -235,7 +236,7 @@ public class LocaleEnhanceTest { for (int i = 0; i < invalids.length; ++i) { String id = invalids[i]; Locale l = Locale.forLanguageTag(id); - assertEquals(id, "und", l.toLanguageTag()); + assertEquals("und", l.toLanguageTag(), id); } } @@ -255,14 +256,14 @@ public class LocaleEnhanceTest { // except no_NO_NY Locale tagResult = Locale.forLanguageTag(tag); if (!target.getVariant().equals("NY")) { - assertEquals("tagResult", target, tagResult); + assertEquals(target, tagResult, "tagResult"); } // the builder also recreates the original locale, // except ja_JP_JP, th_TH_TH and no_NO_NY Locale builderResult = builder.setLocale(target).build(); if (target.getVariant().length() != 2) { - assertEquals("builderResult", target, builderResult); + assertEquals(target, builderResult, "builderResult"); } } } @@ -275,11 +276,11 @@ public class LocaleEnhanceTest { BufferedReader br = new BufferedReader( new InputStreamReader( LocaleEnhanceTest.class.getResourceAsStream("icuLocales.txt"), - "UTF-8")); + StandardCharsets.UTF_8)); String id = null; while (null != (id = br.readLine())) { Locale result = Locale.forLanguageTag(id); - assertEquals("ulocale", id, result.toLanguageTag()); + assertEquals(id, result.toLanguageTag(), "ulocale"); } } @@ -291,163 +292,151 @@ public class LocaleEnhanceTest { public void testConstructor() { // all the old weirdness still holds, no new weirdness String[][] tests = { - // language to lower case, region to upper, variant unchanged - // short - { "X", "y", "z", "x", "Y" }, - // long - { "xXxXxXxXxXxX", "yYyYyYyYyYyYyYyY", "zZzZzZzZzZzZzZzZ", - "xxxxxxxxxxxx", "YYYYYYYYYYYYYYYY" }, - // mapped language ids - { "he", "IL", "", "he" }, - { "iw", "IL", "", "he" }, - { "yi", "DE", "", "yi" }, - { "ji", "DE", "", "yi" }, - { "id", "ID", "", "id" }, - { "in", "ID", "", "id" }, - // special variants - { "ja", "JP", "JP" }, - { "th", "TH", "TH" }, - { "no", "NO", "NY" }, - { "no", "NO", "NY" }, - // no canonicalization of 3-letter language codes - { "eng", "US", "" } + // language to lower case, region to upper, variant unchanged + // short + {"X", "y", "z", "x", "Y"}, + // long + {"xXxXxXxXxXxX", "yYyYyYyYyYyYyYyY", "zZzZzZzZzZzZzZzZ", + "xxxxxxxxxxxx", "YYYYYYYYYYYYYYYY"}, + // mapped language ids + {"he", "IL", "", "he"}, + {"iw", "IL", "", "he"}, + {"yi", "DE", "", "yi"}, + {"ji", "DE", "", "yi"}, + {"id", "ID", "", "id"}, + {"in", "ID", "", "id"}, + // special variants + {"ja", "JP", "JP"}, + {"th", "TH", "TH"}, + {"no", "NO", "NY"}, + {"no", "NO", "NY"}, + // no canonicalization of 3-letter language codes + {"eng", "US", ""} }; - for (int i = 0; i < tests.length; ++ i) { + for (int i = 0; i < tests.length; ++i) { String[] test = tests[i]; String id = String.valueOf(i); Locale locale = Locale.of(test[0], test[1], test[2]); - assertEquals(id + " lang", test.length > 3 ? test[3] : test[0], locale.getLanguage()); - assertEquals(id + " region", test.length > 4 ? test[4] : test[1], locale.getCountry()); - assertEquals(id + " variant", test.length > 5 ? test[5] : test[2], locale.getVariant()); + assertEquals(test.length > 3 ? test[3] : test[0], locale.getLanguage(), id + " lang"); + assertEquals(test.length > 4 ? test[4] : test[1], locale.getCountry(), id + " region"); + assertEquals(test.length > 5 ? test[5] : test[2], locale.getVariant(), id + " variant"); } } /// - /// Locale API tests. + /// Locale API Tests /// @Test public void testGetScript() { // forLanguageTag normalizes case Locale locale = Locale.forLanguageTag("und-latn"); - assertEquals("forLanguageTag", "Latn", locale.getScript()); + assertEquals("Latn", locale.getScript(), "forLanguageTag"); // Builder normalizes case locale = new Builder().setScript("LATN").build(); - assertEquals("builder", "Latn", locale.getScript()); + assertEquals("Latn", locale.getScript(), "builder"); // empty string is returned, not null, if there is no script locale = Locale.forLanguageTag("und"); - assertEquals("script is empty string", "", locale.getScript()); + assertEquals("", locale.getScript(), "script is empty string"); } @Test public void testGetExtension() { // forLanguageTag does NOT normalize to hyphen Locale locale = Locale.forLanguageTag("und-a-some_ex-tension"); - assertEquals("some_ex-tension", null, locale.getExtension('a')); + assertNull(locale.getExtension('a'), "some_ex-tension"); // regular extension locale = new Builder().setExtension('a', "some-ex-tension").build(); - assertEquals("builder", "some-ex-tension", locale.getExtension('a')); + assertEquals("some-ex-tension", locale.getExtension('a'), "builder"); // returns null if extension is not present - assertEquals("empty b", null, locale.getExtension('b')); + assertNull(locale.getExtension('b'), "empty b"); // throws exception if extension tag is illegal - new ExpectIAE() { public void call() { Locale.forLanguageTag("").getExtension('\uD800'); }}; + assertThrows(IllegalArgumentException.class, () -> Locale.forLanguageTag("").getExtension('\uD800')); // 'x' is not an extension, it's a private use tag, but it's accessed through this API locale = Locale.forLanguageTag("x-y-z-blork"); - assertEquals("x", "y-z-blork", locale.getExtension('x')); + assertEquals("y-z-blork", locale.getExtension('x'), "x"); } @Test public void testGetExtensionKeys() { Locale locale = Locale.forLanguageTag("und-a-xx-yy-b-zz-ww"); Set result = locale.getExtensionKeys(); - assertEquals("result size", 2, result.size()); - assertTrue("'a','b'", result.contains('a') && result.contains('b')); + assertEquals(2, result.size(), "result size"); + assertTrue(result.contains('a') && result.contains('b'), "'a','b'"); // result is not mutable - try { - result.add('x'); - fail("expected exception on add to extension key set"); - } - catch (UnsupportedOperationException e) { - // ok - } + assertThrows(UnsupportedOperationException.class, () -> result.add('x')); // returns empty set if no extensions locale = Locale.forLanguageTag("und"); - assertTrue("empty result", locale.getExtensionKeys().isEmpty()); + assertTrue(locale.getExtensionKeys().isEmpty(), "empty result"); } @Test public void testGetUnicodeLocaleAttributes() { Locale locale = Locale.forLanguageTag("en-US-u-abc-def"); Set attributes = locale.getUnicodeLocaleAttributes(); - assertEquals("number of attributes", 2, attributes.size()); - assertTrue("attribute abc", attributes.contains("abc")); - assertTrue("attribute def", attributes.contains("def")); + assertEquals(2, attributes.size(), "number of attributes"); + assertTrue(attributes.contains("abc"), "attribute abc"); + assertTrue(attributes.contains("def"), "attribute def"); locale = Locale.forLanguageTag("en-US-u-ca-gregory"); attributes = locale.getUnicodeLocaleAttributes(); - assertTrue("empty attributes", attributes.isEmpty()); + assertTrue(attributes.isEmpty(), "empty attributes"); } @Test public void testGetUnicodeLocaleType() { Locale locale = Locale.forLanguageTag("und-u-co-japanese-nu-thai"); - assertEquals("collation", "japanese", locale.getUnicodeLocaleType("co")); - assertEquals("numbers", "thai", locale.getUnicodeLocaleType("nu")); + assertEquals("japanese", locale.getUnicodeLocaleType("co"), "collation"); + assertEquals("thai", locale.getUnicodeLocaleType("nu"), "numbers"); // Unicode locale extension key is case insensitive - assertEquals("key case", "japanese", locale.getUnicodeLocaleType("Co")); + assertEquals("japanese", locale.getUnicodeLocaleType("Co"), "key case"); // if keyword is not present, returns null - assertEquals("locale keyword not present", null, locale.getUnicodeLocaleType("xx")); + assertNull(locale.getUnicodeLocaleType("xx"), "locale keyword not present"); // if no locale extension is set, returns null locale = Locale.forLanguageTag("und"); - assertEquals("locale extension not present", null, locale.getUnicodeLocaleType("co")); + assertNull(locale.getUnicodeLocaleType("co"), "locale extension not present"); // typeless keyword locale = Locale.forLanguageTag("und-u-kn"); - assertEquals("typeless keyword", "", locale.getUnicodeLocaleType("kn")); + assertEquals("", locale.getUnicodeLocaleType("kn"), "typeless keyword"); // invalid keys throw exception - new ExpectIAE() { public void call() { Locale.forLanguageTag("").getUnicodeLocaleType("q"); }}; - new ExpectIAE() { public void call() { Locale.forLanguageTag("").getUnicodeLocaleType("abcdefghi"); }}; + assertThrows(IllegalArgumentException.class, () -> Locale.forLanguageTag("").getUnicodeLocaleType("q")); + assertThrows(IllegalArgumentException.class, () -> Locale.forLanguageTag("").getUnicodeLocaleType("abcdefghi")); // null argument throws exception - new ExpectNPE() { public void call() { Locale.forLanguageTag("").getUnicodeLocaleType(null); }}; + assertThrows(NullPointerException.class, () -> Locale.forLanguageTag("").getUnicodeLocaleType(null)); } @Test public void testGetUnicodeLocaleKeys() { Locale locale = Locale.forLanguageTag("und-u-co-japanese-nu-thai"); Set result = locale.getUnicodeLocaleKeys(); - assertEquals("two keys", 2, result.size()); - assertTrue("co and nu", result.contains("co") && result.contains("nu")); + assertEquals(2, result.size(), "two keys"); + assertTrue(result.contains("co") && result.contains("nu"), "co and nu"); // result is not modifiable - try { - result.add("frobozz"); - fail("expected exception when add to locale key set"); - } - catch (UnsupportedOperationException e) { - // ok - } + assertThrows(UnsupportedOperationException.class, () -> result.add("frobozz")); } @Test public void testPrivateUseExtension() { Locale locale = Locale.forLanguageTag("x-y-x-blork-"); - assertEquals("blork", "y-x-blork", locale.getExtension(Locale.PRIVATE_USE_EXTENSION)); + assertEquals("y-x-blork", locale.getExtension(Locale.PRIVATE_USE_EXTENSION), "blork"); locale = Locale.forLanguageTag("und"); - assertEquals("no privateuse", null, locale.getExtension(Locale.PRIVATE_USE_EXTENSION)); + assertNull(locale.getExtension(Locale.PRIVATE_USE_EXTENSION), "no privateuse"); } @Test @@ -455,63 +444,63 @@ public class LocaleEnhanceTest { // lots of normalization to test here // test locales created using the constructor String[][] tests = { - // empty locale canonicalizes to 'und' - { "", "", "", "und" }, - // variant alone is not a valid Locale, but has a valid language tag - { "", "", "NewYork", "und-NewYork" }, - // standard valid locales - { "", "Us", "", "und-US" }, - { "", "US", "NewYork", "und-US-NewYork" }, - { "EN", "", "", "en" }, - { "EN", "", "NewYork", "en-NewYork" }, - { "EN", "US", "", "en-US" }, - { "EN", "US", "NewYork", "en-US-NewYork" }, - // underscore in variant will be emitted as multiple variant subtags - { "en", "US", "Newer_Yorker", "en-US-Newer-Yorker" }, - // invalid variant subtags are appended as private use - { "en", "US", "new_yorker", "en-US-x-lvariant-new-yorker" }, - // the first invalid variant subtags and following variant subtags are appended as private use - { "en", "US", "Windows_XP_Home", "en-US-Windows-x-lvariant-XP-Home" }, - // too long variant and following variant subtags disappear - { "en", "US", "WindowsVista_SP2", "en-US" }, - // invalid region subtag disappears - { "en", "USA", "", "en" }, - // invalid language tag disappears - { "e", "US", "", "und-US" }, - // three-letter language tags are not canonicalized - { "Eng", "", "", "eng" }, - // legacy languages canonicalize to modern equivalents - { "he", "IL", "", "he-IL" }, - { "iw", "IL", "", "he-IL" }, - { "yi", "DE", "", "yi-DE" }, - { "ji", "DE", "", "yi-DE" }, - { "id", "ID", "", "id-ID" }, - { "in", "ID", "", "id-ID" }, - // special values are converted on output - { "ja", "JP", "JP", "ja-JP-u-ca-japanese-x-lvariant-JP" }, - { "th", "TH", "TH", "th-TH-u-nu-thai-x-lvariant-TH" }, - { "no", "NO", "NY", "nn-NO" } + // empty locale canonicalizes to 'und' + {"", "", "", "und"}, + // variant alone is not a valid Locale, but has a valid language tag + {"", "", "NewYork", "und-NewYork"}, + // standard valid locales + {"", "Us", "", "und-US"}, + {"", "US", "NewYork", "und-US-NewYork"}, + {"EN", "", "", "en"}, + {"EN", "", "NewYork", "en-NewYork"}, + {"EN", "US", "", "en-US"}, + {"EN", "US", "NewYork", "en-US-NewYork"}, + // underscore in variant will be emitted as multiple variant subtags + {"en", "US", "Newer_Yorker", "en-US-Newer-Yorker"}, + // invalid variant subtags are appended as private use + {"en", "US", "new_yorker", "en-US-x-lvariant-new-yorker"}, + // the first invalid variant subtags and following variant subtags are appended as private use + {"en", "US", "Windows_XP_Home", "en-US-Windows-x-lvariant-XP-Home"}, + // too long variant and following variant subtags disappear + {"en", "US", "WindowsVista_SP2", "en-US"}, + // invalid region subtag disappears + {"en", "USA", "", "en"}, + // invalid language tag disappears + {"e", "US", "", "und-US"}, + // three-letter language tags are not canonicalized + {"Eng", "", "", "eng"}, + // legacy languages canonicalize to modern equivalents + {"he", "IL", "", "he-IL"}, + {"iw", "IL", "", "he-IL"}, + {"yi", "DE", "", "yi-DE"}, + {"ji", "DE", "", "yi-DE"}, + {"id", "ID", "", "id-ID"}, + {"in", "ID", "", "id-ID"}, + // special values are converted on output + {"ja", "JP", "JP", "ja-JP-u-ca-japanese-x-lvariant-JP"}, + {"th", "TH", "TH", "th-TH-u-nu-thai-x-lvariant-TH"}, + {"no", "NO", "NY", "nn-NO"} }; for (int i = 0; i < tests.length; ++i) { String[] test = tests[i]; Locale locale = Locale.of(test[0], test[1], test[2]); - assertEquals("case " + i, test[3], locale.toLanguageTag()); + assertEquals(test[3], locale.toLanguageTag(), "case " + i); } // test locales created from forLanguageTag String[][] tests1 = { - // case is normalized during the round trip - { "EN-us", "en-US" }, - { "en-Latn-US", "en-Latn-US" }, - // reordering Unicode locale extensions - { "de-u-co-phonebk-ca-gregory", "de-u-ca-gregory-co-phonebk" }, - // private use only language tag is preserved (no extra "und") - { "x-elmer", "x-elmer" }, - { "x-lvariant-JP", "x-lvariant-JP" }, + // case is normalized during the round trip + {"EN-us", "en-US"}, + {"en-Latn-US", "en-Latn-US"}, + // reordering Unicode locale extensions + {"de-u-co-phonebk-ca-gregory", "de-u-ca-gregory-co-phonebk"}, + // private use only language tag is preserved (no extra "und") + {"x-elmer", "x-elmer"}, + {"x-lvariant-JP", "x-lvariant-JP"}, }; for (String[] test : tests1) { Locale locale = Locale.forLanguageTag(test[0]); - assertEquals("case " + test[0], test[1], locale.toLanguageTag()); + assertEquals(test[1], locale.toLanguageTag(), "case " + test[0]); } } @@ -524,102 +513,101 @@ public class LocaleEnhanceTest { // sample private use tags) come from 4646bis Feb 29, 2009. String[][] tests = { - // private use tags only - { "x-abc", "x-abc" }, - { "x-a-b-c", "x-a-b-c" }, - { "x-a-12345678", "x-a-12345678" }, + // private use tags only + {"x-abc", "x-abc"}, + {"x-a-b-c", "x-a-b-c"}, + {"x-a-12345678", "x-a-12345678"}, - // legacy language tags with preferred mappings - { "i-ami", "ami" }, - { "i-bnn", "bnn" }, - { "i-hak", "hak" }, - { "i-klingon", "tlh" }, - { "i-lux", "lb" }, // two-letter tag - { "i-navajo", "nv" }, // two-letter tag - { "i-pwn", "pwn" }, - { "i-tao", "tao" }, - { "i-tay", "tay" }, - { "i-tsu", "tsu" }, - { "art-lojban", "jbo" }, - { "no-bok", "nb" }, - { "no-nyn", "nn" }, - { "sgn-BE-FR", "sfb" }, - { "sgn-BE-NL", "vgt" }, - { "sgn-CH-DE", "sgg" }, - { "zh-guoyu", "cmn" }, - { "zh-hakka", "hak" }, - { "zh-min-nan", "nan" }, - { "zh-xiang", "hsn" }, + // legacy language tags with preferred mappings + {"i-ami", "ami"}, + {"i-bnn", "bnn"}, + {"i-hak", "hak"}, + {"i-klingon", "tlh"}, + {"i-lux", "lb"}, // two-letter tag + {"i-navajo", "nv"}, // two-letter tag + {"i-pwn", "pwn"}, + {"i-tao", "tao"}, + {"i-tay", "tay"}, + {"i-tsu", "tsu"}, + {"art-lojban", "jbo"}, + {"no-bok", "nb"}, + {"no-nyn", "nn"}, + {"sgn-BE-FR", "sfb"}, + {"sgn-BE-NL", "vgt"}, + {"sgn-CH-DE", "sgg"}, + {"zh-guoyu", "cmn"}, + {"zh-hakka", "hak"}, + {"zh-min-nan", "nan"}, + {"zh-xiang", "hsn"}, - // irregular legacy language tags, no preferred mappings, drop illegal fields - // from end. If no subtag is mappable, fallback to 'und' - { "i-default", "en-x-i-default" }, - { "i-enochian", "x-i-enochian" }, - { "i-mingo", "see-x-i-mingo" }, - { "en-GB-oed", "en-GB-x-oed" }, - { "zh-min", "nan-x-zh-min" }, - { "cel-gaulish", "xtg-x-cel-gaulish" }, + // irregular legacy language tags, no preferred mappings, drop illegal fields + // from end. If no subtag is mappable, fallback to 'und' + {"i-default", "en-x-i-default"}, + {"i-enochian", "x-i-enochian"}, + {"i-mingo", "see-x-i-mingo"}, + {"en-GB-oed", "en-GB-x-oed"}, + {"zh-min", "nan-x-zh-min"}, + {"cel-gaulish", "xtg-x-cel-gaulish"}, }; for (int i = 0; i < tests.length; ++i) { String[] test = tests[i]; Locale locale = Locale.forLanguageTag(test[0]); - assertEquals("legacy language tag case " + i, test[1], locale.toLanguageTag()); + assertEquals(test[1], locale.toLanguageTag(), "legacy language tag case " + i); } // forLanguageTag ignores everything past the first place it encounters // a syntax error - tests = new String[][] { - { "valid", - "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x-y-12345678-z", - "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x-y-12345678-z" }, - { "segment of private use tag too long", - "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x-y-123456789-z", - "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x-y" }, - { "segment of private use tag is empty", - "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x-y--12345678-z", - "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x-y" }, - { "first segment of private use tag is empty", - "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x--y-12345678-z", - "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def" }, - { "illegal extension tag", - "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-\uD800-y-12345678-z", - "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def" }, - { "locale subtag with no value", - "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-x-y-12345678-z", - "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-x-y-12345678-z" }, - { "locale key subtag invalid", - "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-123456789-def-x-y-12345678-z", - "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc" }, - // locale key subtag invalid in earlier position, all following subtags - // dropped (and so the locale extension dropped as well) - { "locale key subtag invalid in earlier position", - "en-US-Newer-Yorker-a-bb-cc-dd-u-123456789-abc-bb-def-x-y-12345678-z", - "en-US-Newer-Yorker-a-bb-cc-dd" }, + tests = new String[][]{ + {"valid", + "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x-y-12345678-z", + "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x-y-12345678-z"}, + {"segment of private use tag too long", + "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x-y-123456789-z", + "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x-y"}, + {"segment of private use tag is empty", + "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x-y--12345678-z", + "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x-y"}, + {"first segment of private use tag is empty", + "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-x--y-12345678-z", + "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def"}, + {"illegal extension tag", + "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def-\uD800-y-12345678-z", + "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-def"}, + {"locale subtag with no value", + "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-x-y-12345678-z", + "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-bb-x-y-12345678-z"}, + {"locale key subtag invalid", + "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc-123456789-def-x-y-12345678-z", + "en-US-Newer-Yorker-a-bb-cc-dd-u-aa-abc"}, + // locale key subtag invalid in earlier position, all following subtags + // dropped (and so the locale extension dropped as well) + {"locale key subtag invalid in earlier position", + "en-US-Newer-Yorker-a-bb-cc-dd-u-123456789-abc-bb-def-x-y-12345678-z", + "en-US-Newer-Yorker-a-bb-cc-dd"}, }; for (int i = 0; i < tests.length; ++i) { String[] test = tests[i]; String msg = "syntax error case " + i + " " + test[0]; try { Locale locale = Locale.forLanguageTag(test[1]); - assertEquals(msg, test[2], locale.toLanguageTag()); - } - catch (IllegalArgumentException e) { + assertEquals(test[2], locale.toLanguageTag(), msg); + } catch (IllegalArgumentException e) { fail(msg + " caught exception: " + e); } } // duplicated extension are just ignored Locale locale = Locale.forLanguageTag("und-d-aa-00-bb-01-D-AA-10-cc-11-c-1234"); - assertEquals("extension", "aa-00-bb-01", locale.getExtension('d')); - assertEquals("extension c", "1234", locale.getExtension('c')); + assertEquals("aa-00-bb-01", locale.getExtension('d'), "extension"); + assertEquals("1234", locale.getExtension('c'), "extension c"); locale = Locale.forLanguageTag("und-U-ca-gregory-u-ca-japanese"); - assertEquals("Unicode extension", "ca-gregory", locale.getExtension(Locale.UNICODE_LOCALE_EXTENSION)); + assertEquals("ca-gregory", locale.getExtension(Locale.UNICODE_LOCALE_EXTENSION), "Unicode extension"); // redundant Unicode locale keys in an extension are ignored locale = Locale.forLanguageTag("und-u-aa-000-bb-001-bB-002-cc-003-c-1234"); - assertEquals("Unicode keywords", "aa-000-bb-001-cc-003", locale.getExtension(Locale.UNICODE_LOCALE_EXTENSION)); - assertEquals("Duplicated Unicode locake key followed by an extension", "1234", locale.getExtension('c')); + assertEquals("aa-000-bb-001-cc-003", locale.getExtension(Locale.UNICODE_LOCALE_EXTENSION), "Unicode keywords"); + assertEquals("1234", locale.getExtension('c'), "Duplicated Unicode locake key followed by an extension"); } @Test @@ -630,12 +618,12 @@ public class LocaleEnhanceTest { Locale oldLocale = Locale.getDefault(); Locale.setDefault(Locale.US); - assertEquals("latn US", "Latin", latnLocale.getDisplayScript()); - assertEquals("hans US", "Simplified", hansLocale.getDisplayScript()); + assertEquals("Latin", latnLocale.getDisplayScript(), "latn US"); + assertEquals("Simplified", hansLocale.getDisplayScript(), "hans US"); Locale.setDefault(Locale.GERMANY); - assertEquals("latn DE", "Lateinisch", latnLocale.getDisplayScript()); - assertEquals("hans DE", "Vereinfacht", hansLocale.getDisplayScript()); + assertEquals("Lateinisch", latnLocale.getDisplayScript(), "latn DE"); + assertEquals("Vereinfacht", hansLocale.getDisplayScript(), "hans DE"); Locale.setDefault(oldLocale); } @@ -645,11 +633,11 @@ public class LocaleEnhanceTest { Locale latnLocale = Locale.forLanguageTag("und-latn"); Locale hansLocale = Locale.forLanguageTag("und-hans"); - assertEquals("latn US", "Latin", latnLocale.getDisplayScript(Locale.US)); - assertEquals("hans US", "Simplified", hansLocale.getDisplayScript(Locale.US)); + assertEquals("Latin", latnLocale.getDisplayScript(Locale.US), "latn US"); + assertEquals("Simplified", hansLocale.getDisplayScript(Locale.US), "hans US"); - assertEquals("latn DE", "Lateinisch", latnLocale.getDisplayScript(Locale.GERMANY)); - assertEquals("hans DE", "Vereinfacht", hansLocale.getDisplayScript(Locale.GERMANY)); + assertEquals("Lateinisch", latnLocale.getDisplayScript(Locale.GERMANY), "latn DE"); + assertEquals("Vereinfacht", hansLocale.getDisplayScript(Locale.GERMANY), "hans DE"); } @Test @@ -695,10 +683,10 @@ public class LocaleEnhanceTest { for (int i = 0; i < testLocales.length; i++) { Locale loc = testLocales[i]; - assertEquals("English display name for " + loc.toLanguageTag(), - displayNameEnglish[i], loc.getDisplayName(Locale.ENGLISH)); - assertEquals("Simplified Chinese display name for " + loc.toLanguageTag(), - displayNameSimplifiedChinese[i], loc.getDisplayName(Locale.CHINA)); + assertEquals(displayNameEnglish[i], loc.getDisplayName(Locale.ENGLISH), + "English display name for " + loc.toLanguageTag()); + assertEquals(displayNameSimplifiedChinese[i], loc.getDisplayName(Locale.CHINA), + "Simplified Chinese display name for " + loc.toLanguageTag()); } } @@ -716,37 +704,33 @@ public class LocaleEnhanceTest { Locale locale = Locale.forLanguageTag(languageTag); Locale result = lenientBuilder - .setLocale(locale) - .build(); - assertEquals("long tag", target, result.toLanguageTag()); - assertEquals("long tag", locale, result); + .setLocale(locale) + .build(); + assertEquals(target, result.toLanguageTag(), "long tag"); + assertEquals(locale, result, "long tag"); // null is illegal - new BuilderNPE("locale") { - public void call() { b.setLocale(null); } - }; + assertThrows(NullPointerException.class, () -> builder.setLocale(null), + "Setting null locale should throw NPE"); // builder canonicalizes the three legacy locales: // ja_JP_JP, th_TH_TH, no_NY_NO. locale = builder.setLocale(Locale.of("ja", "JP", "JP")).build(); - assertEquals("ja_JP_JP languagetag", "ja-JP-u-ca-japanese", locale.toLanguageTag()); - assertEquals("ja_JP_JP variant", "", locale.getVariant()); + assertEquals("ja-JP-u-ca-japanese", locale.toLanguageTag(), "ja_JP_JP languagetag"); + assertEquals("", locale.getVariant(), "ja_JP_JP variant"); locale = builder.setLocale(Locale.of("th", "TH", "TH")).build(); - assertEquals("th_TH_TH languagetag", "th-TH-u-nu-thai", locale.toLanguageTag()); - assertEquals("th_TH_TH variant", "", locale.getVariant()); + assertEquals("th-TH-u-nu-thai", locale.toLanguageTag(), "th_TH_TH languagetag"); + assertEquals("", locale.getVariant(), "th_TH_TH variant"); locale = builder.setLocale(Locale.of("no", "NO", "NY")).build(); - assertEquals("no_NO_NY languagetag", "nn-NO", locale.toLanguageTag()); - assertEquals("no_NO_NY language", "nn", locale.getLanguage()); - assertEquals("no_NO_NY variant", "", locale.getVariant()); + assertEquals("nn-NO", locale.toLanguageTag(), "no_NO_NY languagetag"); + assertEquals("nn", locale.getLanguage(), "no_NO_NY language"); + assertEquals("", locale.getVariant(), "no_NO_NY variant"); // non-canonical, non-legacy locales are invalid - new BuilderILE("123_4567_89") { - public void call() { - b.setLocale(Locale.of("123", "4567", "89")); - } - }; + assertThrows(IllformedLocaleException.class, + () -> new Builder().setLocale(Locale.of("123", "4567", "89")), "123_4567_89"); } @Test @@ -755,16 +739,20 @@ public class LocaleEnhanceTest { String target = "en-Latn-US-NewYork-a-xx-b-yy-x-1-2-3"; Builder builder = new Builder(); String result = builder - .setLanguageTag(source) - .build() - .toLanguageTag(); - assertEquals("language", target, result); + .setLanguageTag(source) + .build() + .toLanguageTag(); + assertEquals(target, result, "language"); - // redundant extensions cause a failure - new BuilderILE() { public void call() { b.setLanguageTag("und-a-xx-yy-b-ww-A-00-11-c-vv"); }}; - - // redundant Unicode locale extension keys within an Unicode locale extension cause a failure - new BuilderILE() { public void call() { b.setLanguageTag("und-u-nu-thai-NU-chinese-xx-1234"); }}; + // redundant extensions are ignored + assertEquals("und-a-xx-yy-b-ww-c-vv", + new Builder().setLanguageTag("und-a-xx-yy-b-ww-A-00-11-c-vv").build().toLanguageTag()); + // redundant Unicode locale extension keys are ignored + assertEquals("und-u-cu-usd-nu-thai-xx-1234", + new Builder().setLanguageTag("und-u-nu-thai-cu-usd-NU-chinese-xx-1234").build().toLanguageTag()); + // redundant Unicode locale extension attributes are ignored + assertEquals("und-u-bar-foo", + new Builder().setLanguageTag("und-u-foo-bar-FOO").build().toLanguageTag()); } // Test the values that should clear the builder @@ -776,9 +764,9 @@ public class LocaleEnhanceTest { var bldr = new Builder(); bldr.setLanguageTag("en-US"); assertDoesNotThrow(() -> bldr.setLanguageTag(tag)); - assertEquals("Setting a %s language tag did not clear the builder" - .formatted(tag == null ? "null" : "empty"), - empty.build(), bldr.build()); + assertEquals(empty.build(), bldr.build(), + "Setting a %s language tag did not clear the builder" + .formatted(tag == null ? "null" : "empty")); } @Test @@ -789,18 +777,18 @@ public class LocaleEnhanceTest { String defaulted = ""; Builder builder = new Builder(); String result = builder - .setLanguage(source) - .build() - .getLanguage(); - assertEquals("en", target, result); + .setLanguage(source) + .build() + .getLanguage(); + assertEquals(target, result, "en"); // setting with empty resets result = builder - .setLanguage(target) - .setLanguage("") - .build() - .getLanguage(); - assertEquals("empty", defaulted, result); + .setLanguage(target) + .setLanguage("") + .build() + .getLanguage(); + assertEquals(defaulted, result, "empty"); // setting with null resets too result = builder @@ -808,23 +796,25 @@ public class LocaleEnhanceTest { .setLanguage(null) .build() .getLanguage(); - assertEquals("null", defaulted, result); + assertEquals(defaulted, result, "null"); // language codes must be 2-8 alpha // for forwards compatibility, 4-alpha and 5-8 alpha (registered) // languages are accepted syntax - new BuilderILE("q", "abcdefghi", "13") { public void call() { b.setLanguage(arg); }}; + for (String arg : List.of("q", "abcdefghi", "13")) { + assertThrows(IllformedLocaleException.class, () -> new Builder().setLanguage(arg)); + } // language code validation is NOT performed, any 2-8-alpha passes - assertNotNull("2alpha", builder.setLanguage("zz").build()); - assertNotNull("8alpha", builder.setLanguage("abcdefgh").build()); + assertNotNull(builder.setLanguage("zz").build(), "2alpha"); + assertNotNull(builder.setLanguage("abcdefgh").build(), "8alpha"); // three-letter language codes are NOT canonicalized to two-letter result = builder - .setLanguage("eng") - .build() - .getLanguage(); - assertEquals("eng", "eng", result); + .setLanguage("eng") + .build() + .getLanguage(); + assertEquals("eng", result, "eng"); } @Test @@ -835,18 +825,18 @@ public class LocaleEnhanceTest { String defaulted = ""; Builder builder = new Builder(); String result = builder - .setScript(source) - .build() - .getScript(); - assertEquals("script", target, result); + .setScript(source) + .build() + .getScript(); + assertEquals(target, result, "script"); // setting with empty resets result = builder - .setScript(target) - .setScript("") - .build() - .getScript(); - assertEquals("empty", defaulted, result); + .setScript(target) + .setScript("") + .build() + .getScript(); + assertEquals(defaulted, result, "empty"); // settting with null also resets result = builder @@ -854,14 +844,17 @@ public class LocaleEnhanceTest { .setScript(null) .build() .getScript(); - assertEquals("null", defaulted, result); + assertEquals(defaulted, result, "null"); // ill-formed script codes throw IAE // must be 4alpha - new BuilderILE("abc", "abcde", "l3tn") { public void call() { b.setScript(arg); }}; + for (String arg : List.of("abc", "abcde", "l3tn")) { + assertThrows(IllformedLocaleException.class, () -> new Builder().setScript(arg)); + } + // script code validation is NOT performed, any 4-alpha passes - assertEquals("4alpha", "Wxyz", builder.setScript("wxyz").build().getScript()); + assertEquals("Wxyz", builder.setScript("wxyz").build().getScript(), "4alpha"); } @Test @@ -872,18 +865,18 @@ public class LocaleEnhanceTest { String defaulted = ""; Builder builder = new Builder(); String result = builder - .setRegion(source) - .build() - .getCountry(); - assertEquals("us", target, result); + .setRegion(source) + .build() + .getCountry(); + assertEquals(target, result, "us"); // setting with empty resets result = builder - .setRegion(target) - .setRegion("") - .build() - .getCountry(); - assertEquals("empty", defaulted, result); + .setRegion(target) + .setRegion("") + .build() + .getCountry(); + assertEquals(defaulted, result, "empty"); // setting with null also resets result = builder @@ -891,15 +884,17 @@ public class LocaleEnhanceTest { .setRegion(null) .build() .getCountry(); - assertEquals("null", defaulted, result); + assertEquals(defaulted, result, "null"); // ill-formed region codes throw IAE // 2 alpha or 3 numeric - new BuilderILE("q", "abc", "12", "1234", "a3", "12a") { public void call() { b.setRegion(arg); }}; + for (String arg : List.of("q", "abc", "12", "1234", "a3", "12a")) { + assertThrows(IllformedLocaleException.class, () -> new Builder().setRegion(arg)); + } // region code validation is NOT performed, any 2-alpha or 3-digit passes - assertEquals("2alpha", "ZZ", builder.setRegion("ZZ").build().getCountry()); - assertEquals("3digit", "000", builder.setRegion("000").build().getCountry()); + assertEquals("ZZ", builder.setRegion("ZZ").build().getCountry(), "2alpha"); + assertEquals("000", builder.setRegion("000").build().getCountry(), "3digit"); } @Test @@ -910,31 +905,31 @@ public class LocaleEnhanceTest { String defaulted = ""; Builder builder = new Builder(); String result = builder - .setVariant(source) - .build() - .getVariant(); - assertEquals("NewYork", target, result); + .setVariant(source) + .build() + .getVariant(); + assertEquals(target, result, "NewYork"); result = builder - .setVariant("NeWeR_YoRkEr") - .build() - .toLanguageTag(); - assertEquals("newer yorker", "und-NeWeR-YoRkEr", result); + .setVariant("NeWeR_YoRkEr") + .build() + .toLanguageTag(); + assertEquals("und-NeWeR-YoRkEr", result, "newer yorker"); // subtags of variant are NOT reordered result = builder - .setVariant("zzzzz_yyyyy_xxxxx") - .build() - .getVariant(); - assertEquals("zyx", "zzzzz_yyyyy_xxxxx", result); + .setVariant("zzzzz_yyyyy_xxxxx") + .build() + .getVariant(); + assertEquals("zzzzz_yyyyy_xxxxx", result, "zyx"); // setting to empty resets result = builder - .setVariant(target) - .setVariant("") - .build() - .getVariant(); - assertEquals("empty", defaulted, result); + .setVariant(target) + .setVariant("") + .build() + .getVariant(); + assertEquals(defaulted, result, "empty"); // setting to null also resets result = builder @@ -942,17 +937,21 @@ public class LocaleEnhanceTest { .setVariant(null) .build() .getVariant(); - assertEquals("null", defaulted, result); + assertEquals(defaulted, result, "null"); // ill-formed variants throw IAE // digit followed by 3-7 characters, or alpha followed by 4-8 characters. - new BuilderILE("abcd", "abcdefghi", "1ab", "1abcdefgh") { public void call() { b.setVariant(arg); }}; + for (String arg : List.of("abcd", "abcdefghi", "1ab", "1abcdefgh")) { + assertThrows(IllformedLocaleException.class, () -> new Builder().setVariant(arg)); + } + // 4 characters is ok as long as the first is a digit - assertEquals("digit+3alpha", "1abc", builder.setVariant("1abc").build().getVariant()); + assertEquals("1abc", builder.setVariant("1abc").build().getVariant(), "digit+3alpha"); // all subfields must conform - new BuilderILE("abcde-fg") { public void call() { b.setVariant(arg); }}; + assertThrows(IllformedLocaleException.class, () -> new Builder().setVariant("abcde-fg")); + } @Test @@ -963,18 +962,18 @@ public class LocaleEnhanceTest { String target = "ab-abcdefgh-12-12345678"; Builder builder = new Builder(); String result = builder - .setExtension(sourceKey, sourceValue) - .build() - .getExtension(sourceKey); - assertEquals("extension", target, result); + .setExtension(sourceKey, sourceValue) + .build() + .getExtension(sourceKey); + assertEquals(target, result, "extension"); // setting with empty resets result = builder - .setExtension(sourceKey, sourceValue) - .setExtension(sourceKey, "") - .build() - .getExtension(sourceKey); - assertEquals("empty", null, result); + .setExtension(sourceKey, sourceValue) + .setExtension(sourceKey, "") + .build() + .getExtension(sourceKey); + assertNull(result, "empty"); // setting with null also resets result = builder @@ -982,100 +981,120 @@ public class LocaleEnhanceTest { .setExtension(sourceKey, null) .build() .getExtension(sourceKey); - assertEquals("null", null, result); + assertNull(result, "null"); // ill-formed extension keys throw IAE // must be in [0-9a-ZA-Z] - new BuilderILE("$") { public void call() { b.setExtension('$', sourceValue); }}; + assertThrows(IllformedLocaleException.class, + () -> new Builder().setExtension('$', sourceValue)); + // each segment of value must be 2-8 alphanum - new BuilderILE("ab-cd-123456789") { public void call() { b.setExtension(sourceKey, arg); }}; + assertThrows(IllformedLocaleException.class, + () -> new Builder().setExtension(sourceKey, "ab-cd-123456789")); + // no multiple hyphens. - new BuilderILE("ab--cd") { public void call() { b.setExtension(sourceKey, arg); }}; + assertThrows(IllformedLocaleException.class, + () -> new Builder().setExtension(sourceKey, "ab--cd")); + // locale extension key has special handling Locale locale = builder - .setExtension('u', "co-japanese") - .build(); - assertEquals("locale extension", "japanese", locale.getUnicodeLocaleType("co")); + .setExtension('u', "co-japanese") + .build(); + assertEquals("japanese", locale.getUnicodeLocaleType("co"), "locale extension"); // locale extension has same behavior with set locale keyword Locale locale2 = builder - .setUnicodeLocaleKeyword("co", "japanese") - .build(); - assertEquals("locales with extension", locale, locale2); + .setUnicodeLocaleKeyword("co", "japanese") + .build(); + assertEquals(locale, locale2, "locales with extension"); // setting locale extension overrides all previous calls to setLocaleKeyword Locale locale3 = builder - .setExtension('u', "xxx-nu-thai") - .build(); - assertEquals("remove co", null, locale3.getUnicodeLocaleType("co")); - assertEquals("override thai", "thai", locale3.getUnicodeLocaleType("nu")); - assertEquals("override attribute", 1, locale3.getUnicodeLocaleAttributes().size()); + .setExtension('u', "xxx-nu-thai") + .build(); + assertNull(locale3.getUnicodeLocaleType("co"), "remove co"); + assertEquals("thai", locale3.getUnicodeLocaleType("nu"), "override thai"); + assertEquals(1, locale3.getUnicodeLocaleAttributes().size(), "override attribute"); // setting locale keyword extends values already set by the locale extension Locale locale4 = builder - .setUnicodeLocaleKeyword("co", "japanese") - .build(); - assertEquals("extend", "japanese", locale4.getUnicodeLocaleType("co")); - assertEquals("extend", "thai", locale4.getUnicodeLocaleType("nu")); + .setUnicodeLocaleKeyword("co", "japanese") + .build(); + assertEquals("japanese", locale4.getUnicodeLocaleType("co"), "extend"); + assertEquals("thai", locale4.getUnicodeLocaleType("nu"), "extend"); // locale extension subtags are reordered result = builder - .clear() - .setExtension('u', "456-123-zz-123-yy-456-xx-789") - .build() - .toLanguageTag(); - assertEquals("reorder", "und-u-123-456-xx-789-yy-456-zz-123", result); + .clear() + .setExtension('u', "456-123-zz-123-yy-456-xx-789") + .build() + .toLanguageTag(); + assertEquals("und-u-123-456-xx-789-yy-456-zz-123", result, "reorder"); // multiple keyword types result = builder - .clear() - .setExtension('u', "nu-thai-foobar") - .build() - .getUnicodeLocaleType("nu"); - assertEquals("multiple types", "thai-foobar", result); + .clear() + .setExtension('u', "nu-thai-foobar") + .build() + .getUnicodeLocaleType("nu"); + assertEquals("thai-foobar", result, "multiple types"); // redundant locale extensions are ignored result = builder - .clear() - .setExtension('u', "nu-thai-NU-chinese-xx-1234") - .build() - .toLanguageTag(); - assertEquals("duplicate keys", "und-u-nu-thai-xx-1234", result); + .clear() + .setExtension('u', "nu-thai-NU-chinese-xx-1234") + .build() + .toLanguageTag(); + assertEquals("und-u-nu-thai-xx-1234", result, "duplicate keys"); + + // redundant locale attributes are ignored + result = builder + .clear() + .setExtension('u', "posix-posix") + .build() + .toLanguageTag(); + assertEquals("und-u-posix", result, "duplicate attributes"); } @Test public void testBuilderAddUnicodeLocaleAttribute() { Builder builder = new Builder(); Locale locale = builder - .addUnicodeLocaleAttribute("def") - .addUnicodeLocaleAttribute("abc") - .build(); + .addUnicodeLocaleAttribute("def") + .addUnicodeLocaleAttribute("abc") + .build(); Set uattrs = locale.getUnicodeLocaleAttributes(); - assertEquals("number of attributes", 2, uattrs.size()); - assertTrue("attribute abc", uattrs.contains("abc")); - assertTrue("attribute def", uattrs.contains("def")); + assertEquals(2, uattrs.size(), "number of attributes"); + assertTrue(uattrs.contains("abc"), "attribute abc"); + assertTrue(uattrs.contains("def"), "attribute def"); // remove attribute locale = builder.removeUnicodeLocaleAttribute("xxx") - .build(); + .build(); - assertEquals("remove bogus", 2, uattrs.size()); + uattrs = locale.getUnicodeLocaleAttributes(); + assertEquals(2, uattrs.size(), "remove bogus"); // add duplicate locale = builder.addUnicodeLocaleAttribute("abc") - .build(); - assertEquals("add duplicate", 2, uattrs.size()); + .build(); + uattrs = locale.getUnicodeLocaleAttributes(); + assertEquals(2, uattrs.size(), "add duplicate"); // null attribute throws NPE - new BuilderNPE("null attribute") { public void call() { b.addUnicodeLocaleAttribute(null); }}; - new BuilderNPE("null attribute removal") { public void call() { b.removeUnicodeLocaleAttribute(null); }}; + assertThrows(NullPointerException.class, + () -> new Builder().addUnicodeLocaleAttribute(null), "null attribute"); + + assertThrows(NullPointerException.class, + () -> new Builder().removeUnicodeLocaleAttribute(null), "null attribute removal"); // illformed attribute throws IllformedLocaleException - new BuilderILE("invalid attribute") { public void call() { b.addUnicodeLocaleAttribute("ca"); }}; + assertThrows(IllformedLocaleException.class, + () -> new Builder().addUnicodeLocaleAttribute("ca"), "invalid attribute"); } @Test @@ -1083,43 +1102,51 @@ public class LocaleEnhanceTest { // Note: most behavior is tested in testBuilderSetExtension Builder builder = new Builder(); Locale locale = builder - .setUnicodeLocaleKeyword("co", "japanese") - .setUnicodeLocaleKeyword("nu", "thai") - .build(); - assertEquals("co", "japanese", locale.getUnicodeLocaleType("co")); - assertEquals("nu", "thai", locale.getUnicodeLocaleType("nu")); - assertEquals("keys", 2, locale.getUnicodeLocaleKeys().size()); + .setUnicodeLocaleKeyword("co", "japanese") + .setUnicodeLocaleKeyword("nu", "thai") + .build(); + assertEquals("japanese", locale.getUnicodeLocaleType("co"), "co"); + assertEquals("thai", locale.getUnicodeLocaleType("nu"), "nu"); + assertEquals(2, locale.getUnicodeLocaleKeys().size(), "keys"); // can clear a keyword by setting to null, others remain String result = builder - .setUnicodeLocaleKeyword("co", null) - .build() - .toLanguageTag(); - assertEquals("empty co", "und-u-nu-thai", result); + .setUnicodeLocaleKeyword("co", null) + .build() + .toLanguageTag(); + assertEquals("und-u-nu-thai", result, "empty co"); // locale keyword extension goes when all keywords are gone result = builder - .setUnicodeLocaleKeyword("nu", null) - .build() - .toLanguageTag(); - assertEquals("empty nu", "und", result); + .setUnicodeLocaleKeyword("nu", null) + .build() + .toLanguageTag(); + assertEquals("und", result, "empty nu"); // locale keywords are ordered independent of order of addition result = builder - .setUnicodeLocaleKeyword("zz", "012") - .setUnicodeLocaleKeyword("aa", "345") - .build() - .toLanguageTag(); - assertEquals("reordered", "und-u-aa-345-zz-012", result); + .setUnicodeLocaleKeyword("zz", "012") + .setUnicodeLocaleKeyword("aa", "345") + .build() + .toLanguageTag(); + assertEquals("und-u-aa-345-zz-012", result, "reordered"); // null keyword throws NPE - new BuilderNPE("keyword") { public void call() { b.setUnicodeLocaleKeyword(null, "thai"); }}; + assertThrows(NullPointerException.class, + () -> new Builder().setUnicodeLocaleKeyword(null, "thai"), "keyword"); + // well-formed keywords are two alphanum - new BuilderILE("a", "abc") { public void call() { b.setUnicodeLocaleKeyword(arg, "value"); }}; + for (String arg : List.of("a", "abc")) { + assertThrows(IllformedLocaleException.class, + () -> new Builder().setUnicodeLocaleKeyword(arg, "value")); + } // well-formed values are 3-8 alphanum - new BuilderILE("ab", "abcdefghi") { public void call() { b.setUnicodeLocaleKeyword("ab", arg); }}; + for (String arg : List.of("ab", "abcdefghi")) { + assertThrows(IllformedLocaleException.class, + () -> new Builder().setUnicodeLocaleKeyword("ab", arg)); + } } @Test @@ -1129,13 +1156,15 @@ public class LocaleEnhanceTest { String target = "c-b-a"; Builder builder = new Builder(); String result = builder - .setExtension(Locale.PRIVATE_USE_EXTENSION, source) - .build() - .getExtension(Locale.PRIVATE_USE_EXTENSION); - assertEquals("abc", target, result); + .setExtension(Locale.PRIVATE_USE_EXTENSION, source) + .build() + .getExtension(Locale.PRIVATE_USE_EXTENSION); + assertEquals(target, result, "abc"); // multiple hyphens are ill-formed - new BuilderILE("a--b") { public void call() { b.setExtension(Locale.PRIVATE_USE_EXTENSION, arg); }}; + assertThrows(IllformedLocaleException.class, + () -> new Builder().setExtension(Locale.PRIVATE_USE_EXTENSION, "a--b"), + "multiple-hyphens should throw IAE"); } @Test @@ -1144,11 +1173,11 @@ public class LocaleEnhanceTest { Builder builder = new Builder(); Locale locale = Locale.forLanguageTag(monster); String result = builder - .setLocale(locale) - .clear() - .build() - .toLanguageTag(); - assertEquals("clear", "und", result); + .setLocale(locale) + .clear() + .build() + .toLanguageTag(); + assertEquals("und", result, "clear"); } @Test @@ -1164,33 +1193,33 @@ public class LocaleEnhanceTest { @Test public void testSerialize() { final Locale[] testLocales = { - Locale.ROOT, - Locale.ENGLISH, - Locale.US, - Locale.of("en", "US", "Win"), - Locale.of("en", "US", "Win_XP"), - Locale.JAPAN, - Locale.of("ja", "JP", "JP"), - Locale.of("th", "TH"), - Locale.of("th", "TH", "TH"), - Locale.of("no", "NO"), - Locale.of("nb", "NO"), - Locale.of("nn", "NO"), - Locale.of("no", "NO", "NY"), - Locale.of("nn", "NO", "NY"), - Locale.of("he", "IL"), - Locale.of("he", "IL", "var"), - Locale.of("Language", "Country", "Variant"), - Locale.of("", "US"), - Locale.of("", "", "Java"), - Locale.forLanguageTag("en-Latn-US"), - Locale.forLanguageTag("zh-Hans"), - Locale.forLanguageTag("zh-Hant-TW"), - Locale.forLanguageTag("ja-JP-u-ca-japanese"), - Locale.forLanguageTag("und-Hant"), - Locale.forLanguageTag("und-a-123-456"), - Locale.forLanguageTag("en-x-java"), - Locale.forLanguageTag("th-TH-u-ca-buddist-nu-thai-x-lvariant-TH"), + Locale.ROOT, + Locale.ENGLISH, + Locale.US, + Locale.of("en", "US", "Win"), + Locale.of("en", "US", "Win_XP"), + Locale.JAPAN, + Locale.of("ja", "JP", "JP"), + Locale.of("th", "TH"), + Locale.of("th", "TH", "TH"), + Locale.of("no", "NO"), + Locale.of("nb", "NO"), + Locale.of("nn", "NO"), + Locale.of("no", "NO", "NY"), + Locale.of("nn", "NO", "NY"), + Locale.of("he", "IL"), + Locale.of("he", "IL", "var"), + Locale.of("Language", "Country", "Variant"), + Locale.of("", "US"), + Locale.of("", "", "Java"), + Locale.forLanguageTag("en-Latn-US"), + Locale.forLanguageTag("zh-Hans"), + Locale.forLanguageTag("zh-Hant-TW"), + Locale.forLanguageTag("ja-JP-u-ca-japanese"), + Locale.forLanguageTag("und-Hant"), + Locale.forLanguageTag("und-a-123-456"), + Locale.forLanguageTag("en-x-java"), + Locale.forLanguageTag("th-TH-u-ca-buddist-nu-thai-x-lvariant-TH"), }; for (Locale locale : testLocales) { @@ -1205,7 +1234,7 @@ public class LocaleEnhanceTest { ObjectInputStream ois = new ObjectInputStream(bis); Object o = ois.readObject(); - assertEquals("roundtrip " + locale, locale, o); + assertEquals(locale, o, "roundtrip " + locale); } catch (Exception e) { fail(locale + " encountered exception:" + e.getLocalizedMessage()); } @@ -1231,11 +1260,9 @@ public class LocaleEnhanceTest { } if (dataDir == null) { - fail("'dataDir' is null. serialized.data.dir Property value is "+dataDirName); - return; + fail("'dataDir' is null. serialized.data.dir Property value is " + dataDirName); } else if (!dataDir.isDirectory()) { - fail("'dataDir' is not a directory. dataDir: "+dataDir.toString()); - return; + fail("'dataDir' is not a directory. dataDir: " + dataDir.toString()); } File[] files = dataDir.listFiles(); @@ -1261,10 +1288,9 @@ public class LocaleEnhanceTest { // deserialize try (FileInputStream fis = new FileInputStream(testfile); - ObjectInputStream ois = new ObjectInputStream(fis)) - { + ObjectInputStream ois = new ObjectInputStream(fis)) { Object o = ois.readObject(); - assertEquals("Deserialize Java 6 Locale " + locale, o, locale); + assertEquals(o, locale, "Deserialize Java 6 Locale " + locale); } catch (Exception e) { fail("Exception while reading " + testfile.getAbsolutePath() + " - " + e.getMessage()); } @@ -1284,15 +1310,15 @@ public class LocaleEnhanceTest { // extension "nu-thai". // String[][] testdata = { - {"ja-JP-x-lvariant-JP", "ja-JP-u-ca-japanese-x-lvariant-JP"}, // special case 1 - {"ja-JP-x-lvariant-JP-XXX"}, - {"ja-JP-u-ca-japanese-x-lvariant-JP"}, - {"ja-JP-u-ca-gregory-x-lvariant-JP"}, - {"ja-JP-u-cu-jpy-x-lvariant-JP"}, - {"ja-x-lvariant-JP"}, - {"th-TH-x-lvariant-TH", "th-TH-u-nu-thai-x-lvariant-TH"}, // special case 2 - {"th-TH-u-nu-thai-x-lvariant-TH"}, - {"en-US-x-lvariant-JP"}, + {"ja-JP-x-lvariant-JP", "ja-JP-u-ca-japanese-x-lvariant-JP"}, // special case 1 + {"ja-JP-x-lvariant-JP-XXX"}, + {"ja-JP-u-ca-japanese-x-lvariant-JP"}, + {"ja-JP-u-ca-gregory-x-lvariant-JP"}, + {"ja-JP-u-cu-jpy-x-lvariant-JP"}, + {"ja-x-lvariant-JP"}, + {"th-TH-x-lvariant-TH", "th-TH-u-nu-thai-x-lvariant-TH"}, // special case 2 + {"th-TH-u-nu-thai-x-lvariant-TH"}, + {"en-US-x-lvariant-JP"}, }; Builder bldr = new Builder(); @@ -1304,22 +1330,22 @@ public class LocaleEnhanceTest { // forLanguageTag Locale loc = Locale.forLanguageTag(in); String out = loc.toLanguageTag(); - assertEquals("Language tag roundtrip by forLanguageTag with input: " + in, expected, out); + assertEquals(expected, out, "Language tag roundtrip by forLanguageTag with input: " + in); // setLanguageTag bldr.clear(); bldr.setLanguageTag(in); loc = bldr.build(); out = loc.toLanguageTag(); - assertEquals("Language tag roundtrip by Builder.setLanguageTag with input: " + in, expected, out); + assertEquals(expected, out, "Language tag roundtrip by Builder.setLanguageTag with input: " + in); } } @Test public void testBug7023613() { String[][] testdata = { - {"en-Latn", "en__#Latn"}, - {"en-u-ca-japanese", "en__#u-ca-japanese"}, + {"en-Latn", "en__#Latn"}, + {"en-u-ca-japanese", "en__#u-ca-japanese"}, }; for (String[] data : testdata) { @@ -1328,7 +1354,7 @@ public class LocaleEnhanceTest { Locale loc = Locale.forLanguageTag(in); String out = loc.toString(); - assertEquals("Empty country field with non-empty script/extension with input: " + in, expected, out); + assertEquals(expected, out, "Empty country field with non-empty script/extension with input: " + in); } } @@ -1342,7 +1368,7 @@ public class LocaleEnhanceTest { checkCalendar(Locale.of("ja", "JP", "JP"), "java.util.JapaneseImperialCalendar"); checkCalendar(Locale.of("ja", "jp", "JP"), "java.util.JapaneseImperialCalendar"); checkCalendar(Locale.forLanguageTag("en-u-ca-japanese"), - "java.util.JapaneseImperialCalendar"); + "java.util.JapaneseImperialCalendar"); checkDigit(Locale.of("th", "TH", "th"), '0'); checkDigit(Locale.of("th", "th", "th"), '0'); @@ -1353,151 +1379,12 @@ public class LocaleEnhanceTest { private void checkCalendar(Locale loc, String expected) { Calendar cal = Calendar.getInstance(loc); - assertEquals("Wrong calendar", expected, cal.getClass().getName()); + assertEquals(expected, cal.getClass().getName(), "Wrong calendar"); } private void checkDigit(Locale loc, Character expected) { DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(loc); Character zero = dfs.getZeroDigit(); - assertEquals("Wrong digit zero char", expected, zero); - } - - /// - /// utility asserts - /// - - private void assertTrue(String msg, boolean v) { - if (!v) { - fail(msg + ": expected true"); - } - } - - private void assertFalse(String msg, boolean v) { - if (v) { - fail(msg + ": expected false"); - } - } - - private void assertEquals(String msg, Object e, Object v) { - if (e == null ? v != null : !e.equals(v)) { - if (e != null) { - e = "'" + e + "'"; - } - if (v != null) { - v = "'" + v + "'"; - } - fail(msg + ": expected " + e + " but got " + v); - } - } - - private void assertNotEquals(String msg, Object e, Object v) { - if (e == null ? v == null : e.equals(v)) { - if (e != null) { - e = "'" + e + "'"; - } - fail(msg + ": expected not equal " + e); - } - } - - private void assertNull(String msg, Object o) { - if (o != null) { - fail(msg + ": expected null but got '" + o + "'"); - } - } - - private void assertNotNull(String msg, Object o) { - if (o == null) { - fail(msg + ": expected non null"); - } - } - - // not currently used, might get rid of exceptions from the API - private abstract class ExceptionTest { - private final Class exceptionClass; - - ExceptionTest(Class exceptionClass) { - this.exceptionClass = exceptionClass; - } - - public void run() { - String failMsg = null; - try { - call(); - failMsg = "expected " + exceptionClass.getName() + " but no exception thrown."; - } - catch (Exception e) { - if (!exceptionClass.isAssignableFrom(e.getClass())) { - failMsg = "expected " + exceptionClass.getName() + " but caught " + e; - } - } - if (failMsg != null) { - String msg = message(); - msg = msg == null ? "" : msg + " "; - fail(msg + failMsg); - } - } - - public String message() { - return null; - } - - public abstract void call(); - } - - private abstract class ExpectNPE extends ExceptionTest { - ExpectNPE() { - super(NullPointerException.class); - run(); - } - } - - private abstract class BuilderNPE extends ExceptionTest { - protected final String msg; - protected final Builder b = new Builder(); - - BuilderNPE(String msg) { - super(NullPointerException.class); - - this.msg = msg; - - run(); - } - - public String message() { - return msg; - } - } - - private abstract class ExpectIAE extends ExceptionTest { - ExpectIAE() { - super(IllegalArgumentException.class); - run(); - } - } - - private abstract class BuilderILE extends ExceptionTest { - protected final String[] args; - protected final Builder b = new Builder(); - - protected String arg; // mutates during call - - BuilderILE(String... args) { - super(IllformedLocaleException.class); - - this.args = args; - - run(); - } - - public void run() { - for (String arg : args) { - this.arg = arg; - super.run(); - } - } - - public String message() { - return "arg: '" + arg + "'"; - } + assertEquals(expected, zero, "Wrong digit zero char"); } } From f84be36dd59ae6b00aea334944b8266ecf8f5cbd Mon Sep 17 00:00:00 2001 From: William Kemper Date: Fri, 17 Oct 2025 16:54:20 +0000 Subject: [PATCH 0268/1639] 8241066: Shenandoah: fix or cleanup SH::do_full_collection Reviewed-by: shade --- src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp index b2fd32d2fd0..84f5c3362ac 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp @@ -1576,8 +1576,8 @@ void ShenandoahHeap::collect_as_vm_thread(GCCause::Cause cause) { // cycle. We _could_ cancel the concurrent cycle and then try to run a cycle directly // on the VM thread, but this would confuse the control thread mightily and doesn't // seem worth the trouble. Instead, we will have the caller thread run (and wait for) a - // concurrent cycle in the prologue of the heap inspect/dump operation. This is how - // other concurrent collectors in the JVM handle this scenario as well. + // concurrent cycle in the prologue of the heap inspect/dump operation (see VM_HeapDumper::doit_prologue). + // This is how other concurrent collectors in the JVM handle this scenario as well. assert(Thread::current()->is_VM_thread(), "Should be the VM thread"); guarantee(cause == GCCause::_heap_dump || cause == GCCause::_heap_inspection, "Invalid cause"); } @@ -1587,7 +1587,10 @@ void ShenandoahHeap::collect(GCCause::Cause cause) { } void ShenandoahHeap::do_full_collection(bool clear_all_soft_refs) { - //assert(false, "Shouldn't need to do full collections"); + // This method is only called by `CollectedHeap::collect_as_vm_thread`, which we have + // overridden to do nothing. See the comment there for an explanation of how heap inspections + // work for Shenandoah. + ShouldNotReachHere(); } HeapWord* ShenandoahHeap::block_start(const void* addr) const { From a3e41ea6c60eb278da93dbc2daf940f0dc9abd11 Mon Sep 17 00:00:00 2001 From: Kelvin Nilsen Date: Fri, 17 Oct 2025 17:17:03 +0000 Subject: [PATCH 0269/1639] 8368681: Shenandoah: Add documentation comments for ShenandoahAllocationRate Reviewed-by: wkemper, xpeng --- .../shenandoahAdaptiveHeuristics.hpp | 39 +++++++++++++++++++ .../gc/shenandoah/shenandoahGeneration.hpp | 5 +++ 2 files changed, 44 insertions(+) diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.hpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.hpp index 014a4d99131..66bfc3375a3 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.hpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.hpp @@ -32,25 +32,62 @@ #include "memory/allocation.hpp" #include "utilities/numberSeq.hpp" +/** + * ShenanoahAllocationRate maintains a truncated history of recently sampled allocation rates for the purpose of providing + * informed estimates of current and future allocation rates based on weighted averages and standard deviations of the + * truncated history. More recently sampled allocations are weighted more heavily than older samples when computing + * averages and standard deviations. + */ class ShenandoahAllocationRate : public CHeapObj { public: explicit ShenandoahAllocationRate(); + + // Reset the _last_sample_value to zero, _last_sample_time to current time. void allocation_counter_reset(); + // Force an allocation rate sample to be taken, even if the time since last sample is not greater than + // 1s/ShenandoahAdaptiveSampleFrequencyHz, except when current_time - _last_sample_time < MinSampleTime (2 ms). + // The sampled allocation rate is computed from (allocated - _last_sample_value) / (current_time - _last_sample_time). + // Return the newly computed rate if the sample is taken, zero if it is not an appropriate time to add a sample. + // In the case that a new sample is not taken, overwrite unaccounted_bytes_allocated with bytes allocated since + // the previous sample was taken (allocated - _last_sample_value). Otherwise, overwrite unaccounted_bytes_allocated + // with 0. double force_sample(size_t allocated, size_t &unaccounted_bytes_allocated); + + // Add an allocation rate sample if the time since last sample is greater than 1s/ShenandoahAdaptiveSampleFrequencyHz. + // The sampled allocation rate is computed from (allocated - _last_sample_value) / (current_time - _last_sample_time). + // Return the newly computed rate if the sample is taken, zero if it is not an appropriate time to add a sample. double sample(size_t allocated); + // Return an estimate of the upper bound on allocation rate, with the upper bound computed as the weighted average + // of recently sampled instantaneous allocation rates added to sds times the standard deviation computed for the + // sequence of recently sampled average allocation rates. double upper_bound(double sds) const; + + // Test whether rate significantly diverges from the computed average allocation rate. If so, return true. + // Otherwise, return false. Significant divergence is recognized if (rate - _rate.avg()) / _rate.sd() > threshold. bool is_spiking(double rate, double threshold) const; private: + // Return the instantaneous rate calculated from (allocated - _last_sample_value) / (time - _last_sample_time). + // Return Sentinel value 0.0 if (time - _last_sample_time) == 0 or if (allocated <= _last_sample_value). double instantaneous_rate(double time, size_t allocated) const; + // Time at which previous allocation rate sample was collected. double _last_sample_time; + + // Bytes allocated as of the time at which previous allocation rate sample was collected. size_t _last_sample_value; + + // The desired interval of time between consecutive samples of the allocation rate. double _interval_sec; + + // Holds a sequence of the most recently sampled instantaneous allocation rates TruncatedSeq _rate; + + // Holds a sequence of the most recently computed weighted average of allocation rates, with each weighted average + // computed immediately after an instantaneous rate was sampled TruncatedSeq _rate_avg; }; @@ -154,6 +191,8 @@ protected: } public: + // Sample the allocation rate at GC trigger time if possible. Return the number of allocated bytes that were + // not accounted for in the sample. This must be called before resetting bytes allocated since gc start. virtual size_t force_alloc_rate_sample(size_t bytes_allocated) override { size_t unaccounted_bytes; _allocation_rate.force_sample(bytes_allocated, unaccounted_bytes); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp index e6597b3c1e4..76e4412cfed 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp @@ -142,6 +142,11 @@ private: size_t soft_available() const override; size_t bytes_allocated_since_gc_start() const override; + + // Reset the bytes allocated within this generation since the start of GC. The argument initial_bytes_allocated + // is normally zero. In the case that some memory was allocated following the last allocation rate sample that + // precedes the start of GC, the number of bytes allocated is supplied as the initial value of bytes_allocated_since_gc_start. + // We will behave as if these bytes were allocated after the start of GC. void reset_bytes_allocated_since_gc_start(size_t initial_bytes_allocated); void increase_allocated(size_t bytes); From 0103f21635f00d7b4ece0d667cc5c276613d41ff Mon Sep 17 00:00:00 2001 From: Phil Race Date: Fri, 17 Oct 2025 17:57:21 +0000 Subject: [PATCH 0270/1639] 8365077: java.awt.font.NumericShaper violates equals/hashCode contract Reviewed-by: kizune, psadhukhan --- .../classes/java/awt/font/NumericShaper.java | 28 ++++--- .../awt/font/NumericShaper/NSEqualsTest.java | 84 +++++++++++++++++++ 2 files changed, 102 insertions(+), 10 deletions(-) create mode 100644 test/jdk/java/awt/font/NumericShaper/NSEqualsTest.java diff --git a/src/java.desktop/share/classes/java/awt/font/NumericShaper.java b/src/java.desktop/share/classes/java/awt/font/NumericShaper.java index ae507036112..99b59cc2e0e 100644 --- a/src/java.desktop/share/classes/java/awt/font/NumericShaper.java +++ b/src/java.desktop/share/classes/java/awt/font/NumericShaper.java @@ -346,6 +346,19 @@ public final class NumericShaper implements java.io.Serializable { return index < NUM_KEYS ? Range.values()[index] : null; } + private static int toRangeHash(Set ranges) { + int m = 0; + for (Range range : ranges) { + int index = range.ordinal(); + if (index < NUM_KEYS) { + m |= 1 << index; + } else { + m |= (1 << NUM_KEYS) + index; + } + } + return m; + } + private static int toRangeMask(Set ranges) { int m = 0; for (Range range : ranges) { @@ -576,7 +589,7 @@ public final class NumericShaper implements java.io.Serializable { // and a linear probe is ok. private static int ctCache = 0; - private static int ctCacheLimit = contexts.length - 2; + private static final int ctCacheLimit = contexts.length - 2; // warning, synchronize access to this as it modifies state private static int getContextKey(char c) { @@ -1510,6 +1523,9 @@ public final class NumericShaper implements java.io.Serializable { private NumericShaper(int key, int mask) { this.key = key; this.mask = mask; + if (((this.mask & ARABIC) != 0) && ((this.mask & EASTERN_ARABIC) != 0)) { + this.mask &= ~ARABIC; + } } private NumericShaper(Range defaultContext, Set ranges) { @@ -1795,15 +1811,7 @@ public final class NumericShaper implements java.io.Serializable { * @see java.lang.Object#hashCode */ public int hashCode() { - int hash = mask; - if (rangeSet != null) { - // Use the CONTEXTUAL_MASK bit only for the enum-based - // NumericShaper. A deserialized NumericShaper might have - // bit masks. - hash &= CONTEXTUAL_MASK; - hash ^= rangeSet.hashCode(); - } - return hash; + return (rangeSet != null) ? Range.toRangeHash(rangeSet) : (mask & ~CONTEXTUAL_MASK); } /** diff --git a/test/jdk/java/awt/font/NumericShaper/NSEqualsTest.java b/test/jdk/java/awt/font/NumericShaper/NSEqualsTest.java new file mode 100644 index 00000000000..6af73b7efa2 --- /dev/null +++ b/test/jdk/java/awt/font/NumericShaper/NSEqualsTest.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8365077 + * @summary confirm that an instance which is created with Enum ranges is + * equal to another instance which is created with equivalent traditional + * ranges, and that in such a case the hashCodes are also equal. + */ + +import java.awt.font.NumericShaper; +import java.awt.font.NumericShaper.Range; +import static java.awt.font.NumericShaper.Range.*; +import java.util.EnumSet; + +public class NSEqualsTest { + + public static void main(String[] args) { + + for (Range r1 : Range.values()) { + test(r1); + for (Range r2 : Range.values()) { + test(r1, r2); + } + } + } + + static void test(Range r) { + if (r.ordinal() > MONGOLIAN.ordinal()) { + return; + } + int o = 1 << r.ordinal(); + NumericShaper nsr = NumericShaper.getContextualShaper(EnumSet.of(r)); + NumericShaper nso = NumericShaper.getContextualShaper(o); + printAndCompare(nsr, nso); + } + + static void test(Range r1, Range r2) { + if (r1.ordinal() > MONGOLIAN.ordinal() || r2.ordinal() > MONGOLIAN.ordinal()) { + return; + } + int o1 = 1 << r1.ordinal(); + int o2 = 1 << r2.ordinal(); + + NumericShaper nsr = NumericShaper.getContextualShaper(EnumSet.of(r1, r2)); + NumericShaper nso = NumericShaper.getContextualShaper(o1 | o2); + printAndCompare(nsr, nso); + } + + static void printAndCompare(NumericShaper nsr, NumericShaper nso) { + System.err.println(nsr); + System.err.println(nso); + System.err.println(nsr.hashCode() + " vs " + nso.hashCode() + + " equal: " + nsr.equals(nso)); + if (!nsr.equals(nso)) { + throw new RuntimeException("Expected equal"); + } + if (nsr.hashCode() != nso.hashCode()) { + throw new RuntimeException("Different hash codes:"); + } + } +} + From 0cb8ccd89a659eaf1e245cfb7f8c32fb16bff4c7 Mon Sep 17 00:00:00 2001 From: Chad Rakoczy Date: Fri, 17 Oct 2025 18:03:01 +0000 Subject: [PATCH 0271/1639] 8369642: [ubsan] nmethod::nmethod null pointer passed as argument 2 to memcpy Reviewed-by: kvn, mbaesken --- src/hotspot/share/code/nmethod.cpp | 28 ++++++++++++++++------------ src/hotspot/share/code/nmethod.hpp | 8 ++++---- 2 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp index 7274b627f3e..94e11b00e9a 100644 --- a/src/hotspot/share/code/nmethod.cpp +++ b/src/hotspot/share/code/nmethod.cpp @@ -1147,7 +1147,7 @@ nmethod* nmethod::new_nmethod(const methodHandle& method, + align_up(speculations_len , oopSize) #endif + align_up(debug_info->data_size() , oopSize) - + align_up(ImmutableDataReferencesCounterSize, oopSize); + + ImmutableDataReferencesCounterSize; // First, allocate space for immutable data in C heap. address immutable_data = nullptr; @@ -1322,6 +1322,7 @@ nmethod::nmethod( #if INCLUDE_JVMCI _speculations_offset = 0; #endif + _immutable_data_reference_counter_offset = 0; code_buffer->copy_code_and_locs_to(this); code_buffer->copy_values_to(this); @@ -1420,15 +1421,6 @@ nmethod::nmethod(const nmethod &nm) : CodeBlob(nm._name, nm._kind, nm._size, nm. _method = nm._method; _osr_link = nullptr; - // Increment number of references to immutable data to share it between nmethods - _immutable_data_size = nm._immutable_data_size; - if (_immutable_data_size > 0) { - _immutable_data = nm._immutable_data; - set_immutable_data_references_counter(get_immutable_data_references_counter() + 1); - } else { - _immutable_data = blob_end(); - } - _exception_cache = nullptr; _gc_data = nullptr; _oops_do_mark_nmethods = nullptr; @@ -1444,6 +1436,7 @@ nmethod::nmethod(const nmethod &nm) : CodeBlob(nm._name, nm._kind, nm._size, nm. _entry_offset = nm._entry_offset; _verified_entry_offset = nm._verified_entry_offset; _entry_bci = nm._entry_bci; + _immutable_data_size = nm._immutable_data_size; _skipped_instructions_size = nm._skipped_instructions_size; _stub_offset = nm._stub_offset; @@ -1462,6 +1455,15 @@ nmethod::nmethod(const nmethod &nm) : CodeBlob(nm._name, nm._kind, nm._size, nm. #if INCLUDE_JVMCI _speculations_offset = nm._speculations_offset; #endif + _immutable_data_reference_counter_offset = nm._immutable_data_reference_counter_offset; + + // Increment number of references to immutable data to share it between nmethods + if (_immutable_data_size > 0) { + _immutable_data = nm._immutable_data; + set_immutable_data_references_counter(get_immutable_data_references_counter() + 1); + } else { + _immutable_data = blob_end(); + } _orig_pc_offset = nm._orig_pc_offset; _compile_id = nm._compile_id; @@ -1751,9 +1753,11 @@ nmethod::nmethod( #if INCLUDE_JVMCI _speculations_offset = _scopes_data_offset + align_up(debug_info->data_size(), oopSize); - DEBUG_ONLY( int immutable_data_end_offset = _speculations_offset + align_up(speculations_len, oopSize) + align_up(ImmutableDataReferencesCounterSize, oopSize); ) + _immutable_data_reference_counter_offset = _speculations_offset + align_up(speculations_len, oopSize); + DEBUG_ONLY( int immutable_data_end_offset = _immutable_data_reference_counter_offset + ImmutableDataReferencesCounterSize; ) #else - DEBUG_ONLY( int immutable_data_end_offset = _scopes_data_offset + align_up(debug_info->data_size(), oopSize) + align_up(ImmutableDataReferencesCounterSize, oopSize); ) + _immutable_data_reference_counter_offset = _scopes_data_offset + align_up(debug_info->data_size(), oopSize); + DEBUG_ONLY( int immutable_data_end_offset = _immutable_data_reference_counter_offset + ImmutableDataReferencesCounterSize; ) #endif assert(immutable_data_end_offset <= immutable_data_size, "wrong read-only data size: %d > %d", immutable_data_end_offset, immutable_data_size); diff --git a/src/hotspot/share/code/nmethod.hpp b/src/hotspot/share/code/nmethod.hpp index 2332766a47c..883be718b59 100644 --- a/src/hotspot/share/code/nmethod.hpp +++ b/src/hotspot/share/code/nmethod.hpp @@ -250,6 +250,7 @@ class nmethod : public CodeBlob { #if INCLUDE_JVMCI int _speculations_offset; #endif + int _immutable_data_reference_counter_offset; // location in frame (offset for sp) that deopt can store the original // pc during a deopt. @@ -646,12 +647,11 @@ public: #if INCLUDE_JVMCI address scopes_data_end () const { return _immutable_data + _speculations_offset ; } address speculations_begin () const { return _immutable_data + _speculations_offset ; } - address speculations_end () const { return immutable_data_end() - ImmutableDataReferencesCounterSize ; } + address speculations_end () const { return _immutable_data + _immutable_data_reference_counter_offset ; } #else - address scopes_data_end () const { return immutable_data_end() - ImmutableDataReferencesCounterSize ; } + address scopes_data_end () const { return _immutable_data + _immutable_data_reference_counter_offset ; } #endif - - address immutable_data_references_counter_begin () const { return immutable_data_end() - ImmutableDataReferencesCounterSize ; } + address immutable_data_references_counter_begin () const { return _immutable_data + _immutable_data_reference_counter_offset ; } // Sizes int immutable_data_size() const { return _immutable_data_size; } From 6cd7f30d8d4118787401693b8628c72679d37a6a Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Fri, 17 Oct 2025 19:50:04 +0000 Subject: [PATCH 0272/1639] 8369742: Link AOT-linked classes at JVM bootstrap Reviewed-by: kvn, asmehra --- .../share/cds/aotLinkedClassBulkLoader.cpp | 79 +++++++++++++------ .../share/cds/aotLinkedClassBulkLoader.hpp | 16 ++-- src/hotspot/share/cds/cdsConfig.cpp | 3 +- src/hotspot/share/cds/runTimeClassInfo.cpp | 2 +- .../classfile/systemDictionaryShared.cpp | 48 +++++++---- .../classfile/systemDictionaryShared.hpp | 1 + src/hotspot/share/code/nmethod.cpp | 38 +++++++++ src/hotspot/share/code/nmethod.hpp | 5 ++ src/hotspot/share/runtime/serviceThread.cpp | 4 +- src/hotspot/share/runtime/serviceThread.hpp | 5 +- src/hotspot/share/runtime/threads.cpp | 13 ++- test/hotspot/jtreg/TEST.groups | 1 + .../resolvedConstants/ResolvedConstants.java | 7 +- 13 files changed, 159 insertions(+), 63 deletions(-) diff --git a/src/hotspot/share/cds/aotLinkedClassBulkLoader.cpp b/src/hotspot/share/cds/aotLinkedClassBulkLoader.cpp index e7145b25457..3653f9d518c 100644 --- a/src/hotspot/share/cds/aotLinkedClassBulkLoader.cpp +++ b/src/hotspot/share/cds/aotLinkedClassBulkLoader.cpp @@ -42,6 +42,8 @@ #include "oops/trainingData.hpp" #include "runtime/handles.inline.hpp" #include "runtime/java.hpp" +#include "runtime/serviceThread.hpp" +#include "utilities/growableArray.hpp" void AOTLinkedClassBulkLoader::serialize(SerializeClosure* soc) { AOTLinkedClassTable::get()->serialize(soc); @@ -53,6 +55,8 @@ void AOTLinkedClassBulkLoader::serialize(SerializeClosure* soc) { // step in restoring the JVM's state from the snapshot recorded in the AOT cache: other AOT optimizations // such as AOT compiled methods can make direct references to the preloaded classes, knowing that // these classes are guaranteed to be in at least the "loaded" state. +// +// Note: we can't link the classes yet because SharedRuntime is not yet ready to generate adapters. void AOTLinkedClassBulkLoader::preload_classes(JavaThread* current) { preload_classes_impl(current); if (current->has_pending_exception()) { @@ -112,6 +116,44 @@ void AOTLinkedClassBulkLoader::preload_classes_in_table(Array* c } } +// Some cached heap objects may hold references to methods in aot-linked +// classes (via MemberName). We need to make sure all classes are +// linked before executing any bytecode. +void AOTLinkedClassBulkLoader::link_classes(JavaThread* current) { + link_classes_impl(current); + if (current->has_pending_exception()) { + exit_on_exception(current); + } +} + +void AOTLinkedClassBulkLoader::link_classes_impl(TRAPS) { + precond(CDSConfig::is_using_aot_linked_classes()); + + AOTLinkedClassTable* table = AOTLinkedClassTable::get(); + + link_classes_in_table(table->boot1(), CHECK); + link_classes_in_table(table->boot2(), CHECK); + link_classes_in_table(table->platform(), CHECK); + link_classes_in_table(table->app(), CHECK); +} + +void AOTLinkedClassBulkLoader::link_classes_in_table(Array* classes, TRAPS) { + if (classes != nullptr) { + for (int i = 0; i < classes->length(); i++) { + // NOTE: CDSConfig::is_preserving_verification_constraints() is required + // when storing ik in the AOT cache. This means we don't have to verify + // ik at all. + // + // Without is_preserving_verification_constraints(), ik->link_class() may cause + // class loading, which may result in invocation of ClassLoader::loadClass() calls, + // which CANNOT happen because we are not ready to execute any Java byecodes yet + // at this point. + InstanceKlass* ik = classes->at(i); + ik->link_class(CHECK); + } + } +} + #ifdef ASSERT void AOTLinkedClassBulkLoader::validate_module_of_preloaded_classes() { oop javabase_module_oop = ModuleEntryTable::javabase_moduleEntry()->module_oop(); @@ -173,25 +215,21 @@ void AOTLinkedClassBulkLoader::validate_module(Klass* k, const char* category_na } #endif -// Link all java.base classes in the AOTLinkedClassTable. Of those classes, -// move the ones that have been AOT-initialized to the "initialized" state. -void AOTLinkedClassBulkLoader::link_or_init_javabase_classes(JavaThread* current) { - link_or_init_classes_for_loader(Handle(), AOTLinkedClassTable::get()->boot1(), current); +void AOTLinkedClassBulkLoader::init_javabase_classes(JavaThread* current) { + init_classes_for_loader(Handle(), AOTLinkedClassTable::get()->boot1(), current); if (current->has_pending_exception()) { exit_on_exception(current); } } -// Do the same thing as link_or_init_javabase_classes(), but for the classes that are not -// in the java.base module. -void AOTLinkedClassBulkLoader::link_or_init_non_javabase_classes(JavaThread* current) { - link_or_init_non_javabase_classes_impl(current); +void AOTLinkedClassBulkLoader::init_non_javabase_classes(JavaThread* current) { + init_non_javabase_classes_impl(current); if (current->has_pending_exception()) { exit_on_exception(current); } } -void AOTLinkedClassBulkLoader::link_or_init_non_javabase_classes_impl(TRAPS) { +void AOTLinkedClassBulkLoader::init_non_javabase_classes_impl(TRAPS) { assert(CDSConfig::is_using_aot_linked_classes(), "sanity"); DEBUG_ONLY(validate_module_of_preloaded_classes()); @@ -208,9 +246,9 @@ void AOTLinkedClassBulkLoader::link_or_init_non_javabase_classes_impl(TRAPS) { assert(h_system_loader() != nullptr, "must be"); AOTLinkedClassTable* table = AOTLinkedClassTable::get(); - link_or_init_classes_for_loader(Handle(), table->boot2(), CHECK); - link_or_init_classes_for_loader(h_platform_loader, table->platform(), CHECK); - link_or_init_classes_for_loader(h_system_loader, table->app(), CHECK); + init_classes_for_loader(Handle(), table->boot2(), CHECK); + init_classes_for_loader(h_platform_loader, table->platform(), CHECK); + init_classes_for_loader(h_system_loader, table->app(), CHECK); if (Universe::is_fully_initialized() && VerifyDuringStartup) { // Make sure we're still in a clean state. @@ -242,8 +280,9 @@ void AOTLinkedClassBulkLoader::exit_on_exception(JavaThread* current) { log_error(aot)("Out of memory. Please run with a larger Java heap, current MaxHeapSize = " "%zuM", MaxHeapSize/M); } else { + oop message = java_lang_Throwable::message(current->pending_exception()); log_error(aot)("%s: %s", current->pending_exception()->klass()->external_name(), - java_lang_String::as_utf8_string(java_lang_Throwable::message(current->pending_exception()))); + message == nullptr ? "(no message)" : java_lang_String::as_utf8_string(message)); } vm_exit_during_initialization("Unexpected exception when loading aot-linked classes."); } @@ -289,23 +328,13 @@ void AOTLinkedClassBulkLoader::initiate_loading(JavaThread* current, const char* // - classes that were AOT-initialized by AOTClassInitializer // - the classes of all objects that are reachable from the archived mirrors of // the AOT-linked classes for . -void AOTLinkedClassBulkLoader::link_or_init_classes_for_loader(Handle class_loader, Array* classes, TRAPS) { +void AOTLinkedClassBulkLoader::init_classes_for_loader(Handle class_loader, Array* classes, TRAPS) { if (classes != nullptr) { for (int i = 0; i < classes->length(); i++) { InstanceKlass* ik = classes->at(i); - if (ik->class_loader_data() == nullptr) { - // This class is not yet loaded. We will initialize it in a later phase. - // For example, we have loaded only AOTLinkedClassCategory::BOOT1 classes - // but k is part of AOTLinkedClassCategory::BOOT2. - continue; - } + assert(ik->class_loader_data() != nullptr, "must be"); if (ik->has_aot_initialized_mirror()) { ik->initialize_with_aot_initialized_mirror(CHECK); - } else { - // Some cached heap objects may hold references to methods in aot-linked - // classes (via MemberName). We need to make sure all classes are - // linked to allow such MemberNames to be invoked. - ik->link_class(CHECK); } } } diff --git a/src/hotspot/share/cds/aotLinkedClassBulkLoader.hpp b/src/hotspot/share/cds/aotLinkedClassBulkLoader.hpp index 77400a86104..31fdac386fe 100644 --- a/src/hotspot/share/cds/aotLinkedClassBulkLoader.hpp +++ b/src/hotspot/share/cds/aotLinkedClassBulkLoader.hpp @@ -52,10 +52,11 @@ class AOTLinkedClassBulkLoader : AllStatic { static void preload_classes_impl(TRAPS); static void preload_classes_in_table(Array* classes, const char* category_name, Handle loader, TRAPS); - static void initiate_loading(JavaThread* current, const char* category, Handle initiating_loader, - Array* classes); - static void link_or_init_non_javabase_classes_impl(TRAPS); - static void link_or_init_classes_for_loader(Handle class_loader, Array* classes, TRAPS); + static void initiate_loading(JavaThread* current, const char* category, Handle initiating_loader, Array* classes); + static void link_classes_impl(TRAPS); + static void link_classes_in_table(Array* classes, TRAPS); + static void init_non_javabase_classes_impl(TRAPS); + static void init_classes_for_loader(Handle class_loader, Array* classes, TRAPS); static void replay_training_at_init(Array* classes, TRAPS) NOT_CDS_RETURN; #ifdef ASSERT @@ -67,9 +68,10 @@ class AOTLinkedClassBulkLoader : AllStatic { public: static void serialize(SerializeClosure* soc) NOT_CDS_RETURN; - static void preload_classes(JavaThread* current); - static void link_or_init_javabase_classes(JavaThread* current) NOT_CDS_RETURN; - static void link_or_init_non_javabase_classes(JavaThread* current) NOT_CDS_RETURN; + static void preload_classes(JavaThread* current) NOT_CDS_RETURN; + static void link_classes(JavaThread* current) NOT_CDS_RETURN; + static void init_javabase_classes(JavaThread* current) NOT_CDS_RETURN; + static void init_non_javabase_classes(JavaThread* current) NOT_CDS_RETURN; static void exit_on_exception(JavaThread* current); static void replay_training_at_init_for_preloaded_classes(TRAPS) NOT_CDS_RETURN; diff --git a/src/hotspot/share/cds/cdsConfig.cpp b/src/hotspot/share/cds/cdsConfig.cpp index 7c6b925470a..a5d1f78b76f 100644 --- a/src/hotspot/share/cds/cdsConfig.cpp +++ b/src/hotspot/share/cds/cdsConfig.cpp @@ -943,8 +943,9 @@ bool CDSConfig::is_preserving_verification_constraints() { return AOTClassLinking; } else if (is_dumping_final_static_archive()) { // writing AOT cache return is_dumping_aot_linked_classes(); + } else if (is_dumping_classic_static_archive()) { + return is_dumping_aot_linked_classes(); } else { - // For simplicity, we don't support this optimization with the old CDS workflow. return false; } } diff --git a/src/hotspot/share/cds/runTimeClassInfo.cpp b/src/hotspot/share/cds/runTimeClassInfo.cpp index 832b0ce8932..fe940ca6c18 100644 --- a/src/hotspot/share/cds/runTimeClassInfo.cpp +++ b/src/hotspot/share/cds/runTimeClassInfo.cpp @@ -41,7 +41,7 @@ void RunTimeClassInfo::init(DumpTimeClassInfo& info) { _num_loader_constraints = info.num_loader_constraints(); int i; - if (CDSConfig::is_preserving_verification_constraints() && CDSConfig::is_dumping_final_static_archive()) { + if (CDSConfig::is_preserving_verification_constraints()) { // The production run doesn't need the verifier constraints, as we can guarantee that all classes checked by // the verifier during AOT training/assembly phases cannot be replaced in the production run. _num_verifier_constraints = 0; diff --git a/src/hotspot/share/classfile/systemDictionaryShared.cpp b/src/hotspot/share/classfile/systemDictionaryShared.cpp index 2d31a7c49f6..cb2ae96348e 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.cpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp @@ -855,6 +855,28 @@ public: } }; +void SystemDictionaryShared::link_all_exclusion_check_candidates(InstanceKlass* ik) { + bool need_to_link = false; + { + MutexLocker ml(DumpTimeTable_lock, Mutex::_no_safepoint_check_flag); + ExclusionCheckCandidates candidates(ik); + + candidates.iterate_all([&] (InstanceKlass* k, DumpTimeClassInfo* info) { + if (!k->is_linked()) { + need_to_link = true; + } + }); + } + if (need_to_link) { + JavaThread* THREAD = JavaThread::current(); + if (log_is_enabled(Info, aot, link)) { + ResourceMark rm(THREAD); + log_info(aot, link)("Link all loaded classes for %s", ik->external_name()); + } + AOTMetaspace::link_all_loaded_classes(THREAD); + } +} + // Returns true if the class should be excluded. This can be called by // AOTConstantPoolResolver before or after we enter the CDS safepoint. // When called before the safepoint, we need to link the class so that @@ -878,27 +900,19 @@ bool SystemDictionaryShared::should_be_excluded(Klass* k) { InstanceKlass* ik = InstanceKlass::cast(k); if (!SafepointSynchronize::is_at_safepoint()) { - if (!ik->is_linked()) { - // should_be_excluded_impl() below doesn't link unlinked classes. We come - // here only when we are trying to aot-link constant pool entries, so - // we'd better link the class. - JavaThread* THREAD = JavaThread::current(); - ik->link_class(THREAD); - if (HAS_PENDING_EXCEPTION) { - CLEAR_PENDING_EXCEPTION; - return true; // linking failed -- let's exclude it + { + // fast path + MutexLocker ml(DumpTimeTable_lock, Mutex::_no_safepoint_check_flag); + DumpTimeClassInfo* p = get_info_locked(ik); + if (p->has_checked_exclusion()) { + return p->is_excluded(); } - - // Also link any classes that were loaded for the verification of ik or its supertypes. - // Otherwise we might miss the verification constraints of those classes. - AOTMetaspace::link_all_loaded_classes(THREAD); } + link_all_exclusion_check_candidates(ik); + MutexLocker ml(DumpTimeTable_lock, Mutex::_no_safepoint_check_flag); DumpTimeClassInfo* p = get_info_locked(ik); - if (p->is_excluded()) { - return true; - } return should_be_excluded_impl(ik, p); } else { // When called within the CDS safepoint, the correctness of this function @@ -912,7 +926,7 @@ bool SystemDictionaryShared::should_be_excluded(Klass* k) { // No need to check for is_linked() as all eligible classes should have // already been linked in AOTMetaspace::link_class_for_cds(). - // Can't take the lock as we are in safepoint. + // Don't take DumpTimeTable_lock as we are in safepoint. DumpTimeClassInfo* p = _dumptime_table->get(ik); if (p->is_excluded()) { return true; diff --git a/src/hotspot/share/classfile/systemDictionaryShared.hpp b/src/hotspot/share/classfile/systemDictionaryShared.hpp index 5ff57653dd0..2619a642fd1 100644 --- a/src/hotspot/share/classfile/systemDictionaryShared.hpp +++ b/src/hotspot/share/classfile/systemDictionaryShared.hpp @@ -175,6 +175,7 @@ private: static void write_dictionary(RunTimeSharedDictionary* dictionary, bool is_builtin); static bool is_jfr_event_class(InstanceKlass *k); + static void link_all_exclusion_check_candidates(InstanceKlass* ik); static bool should_be_excluded_impl(InstanceKlass* k, DumpTimeClassInfo* info); // exclusion checks diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp index 94e11b00e9a..a99e753180d 100644 --- a/src/hotspot/share/code/nmethod.cpp +++ b/src/hotspot/share/code/nmethod.cpp @@ -23,6 +23,7 @@ */ #include "asm/assembler.inline.hpp" +#include "cds/cdsConfig.hpp" #include "code/codeCache.hpp" #include "code/compiledIC.hpp" #include "code/dependencies.hpp" @@ -2504,11 +2505,48 @@ void nmethod::post_compiled_method(CompileTask* task) { maybe_print_nmethod(directive); } +#if INCLUDE_CDS +static GrowableArrayCHeap* _delayed_compiled_method_load_events = nullptr; + +void nmethod::add_delayed_compiled_method_load_event(nmethod* nm) { + precond(CDSConfig::is_using_aot_linked_classes()); + precond(!ServiceThread::has_started()); + + // We are still in single threaded stage of VM bootstrap. No need to lock. + if (_delayed_compiled_method_load_events == nullptr) { + _delayed_compiled_method_load_events = new GrowableArrayCHeap(); + } + _delayed_compiled_method_load_events->append(nm); +} + +void nmethod::post_delayed_compiled_method_load_events() { + precond(ServiceThread::has_started()); + if (_delayed_compiled_method_load_events != nullptr) { + for (int i = 0; i < _delayed_compiled_method_load_events->length(); i++) { + nmethod* nm = _delayed_compiled_method_load_events->at(i); + nm->post_compiled_method_load_event(); + } + delete _delayed_compiled_method_load_events; + _delayed_compiled_method_load_events = nullptr; + } +} +#endif + // ------------------------------------------------------------------ // post_compiled_method_load_event // new method for install_code() path // Transfer information from compilation to jvmti void nmethod::post_compiled_method_load_event(JvmtiThreadState* state) { +#if INCLUDE_CDS + if (!ServiceThread::has_started()) { + // With AOT-linked classes, we could compile wrappers for native methods before the + // ServiceThread has been started, so we must delay the events to be posted later. + assert(state == nullptr, "must be"); + add_delayed_compiled_method_load_event(this); + return; + } +#endif + // This is a bad time for a safepoint. We don't want // this nmethod to get unloaded while we're queueing the event. NoSafepointVerifier nsv; diff --git a/src/hotspot/share/code/nmethod.hpp b/src/hotspot/share/code/nmethod.hpp index 883be718b59..3763b81f887 100644 --- a/src/hotspot/share/code/nmethod.hpp +++ b/src/hotspot/share/code/nmethod.hpp @@ -965,6 +965,8 @@ public: inline int get_immutable_data_references_counter() { return *((int*)immutable_data_references_counter_begin()); } inline void set_immutable_data_references_counter(int count) { *((int*)immutable_data_references_counter_begin()) = count; } + static void add_delayed_compiled_method_load_event(nmethod* nm) NOT_CDS_RETURN; + public: // ScopeDesc retrieval operation PcDesc* pc_desc_at(address pc) { return find_pc_desc(pc, false); } @@ -999,6 +1001,9 @@ public: // Avoid hiding of parent's 'decode(outputStream*)' method. void decode(outputStream* st) const { decode2(st); } // just delegate here. + // AOT cache support + static void post_delayed_compiled_method_load_events() NOT_CDS_RETURN; + // printing support void print_on_impl(outputStream* st) const; void print_code(); diff --git a/src/hotspot/share/runtime/serviceThread.cpp b/src/hotspot/share/runtime/serviceThread.cpp index 9a0bfe03ac3..03168842e36 100644 --- a/src/hotspot/share/runtime/serviceThread.cpp +++ b/src/hotspot/share/runtime/serviceThread.cpp @@ -45,7 +45,7 @@ #include "services/lowMemoryDetector.hpp" #include "services/threadIdTable.hpp" -DEBUG_ONLY(JavaThread* ServiceThread::_instance = nullptr;) +JavaThread* ServiceThread::_instance = nullptr; JvmtiDeferredEvent* ServiceThread::_jvmti_event = nullptr; // The service thread has it's own static deferred event queue. // Events can be posted before JVMTI vm_start, so it's too early to call JvmtiThreadState::state_for @@ -62,7 +62,7 @@ void ServiceThread::initialize() { JavaThread::vm_exit_on_osthread_failure(thread); JavaThread::start_internal_daemon(THREAD, thread, thread_oop, NearMaxPriority); - DEBUG_ONLY(_instance = thread;) + _instance = thread; } static void cleanup_oopstorages() { diff --git a/src/hotspot/share/runtime/serviceThread.hpp b/src/hotspot/share/runtime/serviceThread.hpp index f65847ece00..cfce8603cd5 100644 --- a/src/hotspot/share/runtime/serviceThread.hpp +++ b/src/hotspot/share/runtime/serviceThread.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,7 +35,7 @@ class JvmtiDeferredEvent; class ServiceThread : public JavaThread { private: - DEBUG_ONLY(static JavaThread* _instance;) + static JavaThread* _instance; static JvmtiDeferredEvent* _jvmti_event; static JvmtiDeferredEventQueue _jvmti_service_queue; @@ -44,6 +44,7 @@ class ServiceThread : public JavaThread { public: static void initialize(); + static bool has_started() { return _instance != nullptr; } // Hide this thread from external view. bool is_hidden_from_external_view() const { return true; } diff --git a/src/hotspot/share/runtime/threads.cpp b/src/hotspot/share/runtime/threads.cpp index ffe1a86cda5..52275049eae 100644 --- a/src/hotspot/share/runtime/threads.cpp +++ b/src/hotspot/share/runtime/threads.cpp @@ -343,6 +343,11 @@ static void call_initPhase3(TRAPS) { void Threads::initialize_java_lang_classes(JavaThread* main_thread, TRAPS) { TraceTime timer("Initialize java.lang classes", TRACETIME_LOG(Info, startuptime)); + // This is before the execution of the very first Java bytecode. + if (CDSConfig::is_using_aot_linked_classes()) { + AOTLinkedClassBulkLoader::link_classes(THREAD); + } + initialize_class(vmSymbols::java_lang_String(), CHECK); // Inject CompactStrings value after the static initializers for String ran. @@ -742,6 +747,10 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { // and other cleanups. Needs to start before the compilers start posting events. ServiceThread::initialize(); + if (CDSConfig::is_using_aot_linked_classes()) { + nmethod::post_delayed_compiled_method_load_events(); + } + // Start the monitor deflation thread: MonitorDeflationThread::initialize(); @@ -774,7 +783,7 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { if (CDSConfig::is_using_aot_linked_classes()) { SystemDictionary::restore_archived_method_handle_intrinsics(); - AOTLinkedClassBulkLoader::link_or_init_javabase_classes(THREAD); + AOTLinkedClassBulkLoader::init_javabase_classes(THREAD); } // Start string deduplication thread if requested. @@ -793,7 +802,7 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { call_initPhase2(CHECK_JNI_ERR); if (CDSConfig::is_using_aot_linked_classes()) { - AOTLinkedClassBulkLoader::link_or_init_non_javabase_classes(THREAD); + AOTLinkedClassBulkLoader::init_non_javabase_classes(THREAD); } #ifndef PRODUCT HeapShared::initialize_test_class_from_archive(THREAD); diff --git a/test/hotspot/jtreg/TEST.groups b/test/hotspot/jtreg/TEST.groups index fd9dd6eb4c0..18f27a96628 100644 --- a/test/hotspot/jtreg/TEST.groups +++ b/test/hotspot/jtreg/TEST.groups @@ -570,6 +570,7 @@ hotspot_aot_classlinking = \ -runtime/cds/appcds/TestSerialGCWithCDS.java \ -runtime/cds/appcds/TestZGCWithCDS.java \ -runtime/cds/appcds/TestWithProfiler.java \ + -runtime/cds/appcds/VerifyObjArrayCloneTest.java \ -runtime/cds/serviceability/ReplaceCriticalClassesForSubgraphs.java \ -runtime/cds/serviceability/ReplaceCriticalClasses.java \ -runtime/cds/serviceability/transformRelatedClasses/TransformInterfaceAndImplementor.java \ diff --git a/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/ResolvedConstants.java b/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/ResolvedConstants.java index bc2ac9db2ab..621d6383ff4 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/ResolvedConstants.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/resolvedConstants/ResolvedConstants.java @@ -174,14 +174,9 @@ public class ResolvedConstants { // Indy References --- if (aotClassLinking) { testGroup("Indy References", out) - .shouldContain("Cannot aot-resolve Lambda proxy because OldConsumer is excluded") - .shouldContain("Cannot aot-resolve Lambda proxy because OldProvider is excluded") - .shouldContain("Cannot aot-resolve Lambda proxy because OldClass is excluded") .shouldContain("Cannot aot-resolve Lambda proxy of interface type InterfaceWithClinit") .shouldMatch("klasses.* app *NormalClass[$][$]Lambda/.* hidden aot-linked inited") - .shouldNotMatch("klasses.* app *SubOfOldClass[$][$]Lambda/") - .shouldMatch("archived indy *CP entry.*StringConcatTest .* => java/lang/invoke/StringConcatFactory.makeConcatWithConstants") - .shouldNotMatch("archived indy *CP entry.*StringConcatTestOld .* => java/lang/invoke/StringConcatFactory.makeConcatWithConstants"); + .shouldMatch("archived indy *CP entry.*StringConcatTest .* => java/lang/invoke/StringConcatFactory.makeConcatWithConstants"); } } From 0cc88e4ad4ded970433eed25778a7290ddf9b0fa Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Fri, 17 Oct 2025 20:38:37 +0000 Subject: [PATCH 0273/1639] 8370028: Remove author tags from mathematical classes Reviewed-by: bpb, rriggs --- src/java.base/share/classes/java/lang/Byte.java | 2 -- src/java.base/share/classes/java/lang/Double.java | 4 ---- src/java.base/share/classes/java/lang/Float.java | 4 ---- src/java.base/share/classes/java/lang/Integer.java | 4 ---- src/java.base/share/classes/java/lang/Long.java | 4 ---- src/java.base/share/classes/java/lang/Math.java | 4 ---- src/java.base/share/classes/java/lang/Short.java | 2 -- src/java.base/share/classes/java/lang/StrictMath.java | 6 ------ src/java.base/share/classes/java/math/BigDecimal.java | 6 ------ src/java.base/share/classes/java/math/MathContext.java | 2 -- src/java.base/share/classes/java/math/RoundingMode.java | 3 --- .../share/classes/jdk/internal/math/DoubleConsts.java | 4 +--- .../share/classes/jdk/internal/math/FloatConsts.java | 4 +--- 13 files changed, 2 insertions(+), 47 deletions(-) diff --git a/src/java.base/share/classes/java/lang/Byte.java b/src/java.base/share/classes/java/lang/Byte.java index accd448a0cd..d9913e354a4 100644 --- a/src/java.base/share/classes/java/lang/Byte.java +++ b/src/java.base/share/classes/java/lang/Byte.java @@ -55,8 +55,6 @@ import static java.lang.constant.ConstantDescs.DEFAULT_NAME; * use instances for synchronization, or unpredictable behavior may * occur. For example, in a future release, synchronization may fail. * - * @author Nakul Saraiya - * @author Joseph D. Darcy * @see java.lang.Number * @since 1.1 */ diff --git a/src/java.base/share/classes/java/lang/Double.java b/src/java.base/share/classes/java/lang/Double.java index 661a0ceb42b..6cee75cea2b 100644 --- a/src/java.base/share/classes/java/lang/Double.java +++ b/src/java.base/share/classes/java/lang/Double.java @@ -352,9 +352,6 @@ import jdk.internal.vm.annotation.IntrinsicCandidate; * @spec https://standards.ieee.org/ieee/754/6210/ * IEEE Standard for Floating-Point Arithmetic * - * @author Lee Boynton - * @author Arthur van Hoff - * @author Joseph D. Darcy * @since 1.0 */ @jdk.internal.ValueBased @@ -695,7 +692,6 @@ public final class Double extends Number * @param d the {@code double} to be converted. * @return a hex string representation of the argument. * @since 1.5 - * @author Joseph D. Darcy */ public static String toHexString(double d) { /* diff --git a/src/java.base/share/classes/java/lang/Float.java b/src/java.base/share/classes/java/lang/Float.java index db694571567..c553dc41c2c 100644 --- a/src/java.base/share/classes/java/lang/Float.java +++ b/src/java.base/share/classes/java/lang/Float.java @@ -70,9 +70,6 @@ import jdk.internal.vm.annotation.IntrinsicCandidate; * @spec https://standards.ieee.org/ieee/754/6210/ * IEEE Standard for Floating-Point Arithmetic * - * @author Lee Boynton - * @author Arthur van Hoff - * @author Joseph D. Darcy * @since 1.0 */ @jdk.internal.ValueBased @@ -411,7 +408,6 @@ public final class Float extends Number * @param f the {@code float} to be converted. * @return a hex string representation of the argument. * @since 1.5 - * @author Joseph D. Darcy */ public static String toHexString(float f) { if (Math.abs(f) < Float.MIN_NORMAL diff --git a/src/java.base/share/classes/java/lang/Integer.java b/src/java.base/share/classes/java/lang/Integer.java index 41487a469b6..6e49f1983aa 100644 --- a/src/java.base/share/classes/java/lang/Integer.java +++ b/src/java.base/share/classes/java/lang/Integer.java @@ -68,10 +68,6 @@ import static java.lang.String.UTF16; * Delight, (Addison Wesley, 2002) and Hacker's * Delight, Second Edition, (Pearson Education, 2013). * - * @author Lee Boynton - * @author Arthur van Hoff - * @author Josh Bloch - * @author Joseph D. Darcy * @since 1.0 */ @jdk.internal.ValueBased diff --git a/src/java.base/share/classes/java/lang/Long.java b/src/java.base/share/classes/java/lang/Long.java index 2fb2d18a78c..90249cb1edb 100644 --- a/src/java.base/share/classes/java/lang/Long.java +++ b/src/java.base/share/classes/java/lang/Long.java @@ -68,10 +68,6 @@ import static java.lang.String.UTF16; * Delight, (Addison Wesley, 2002) and Hacker's * Delight, Second Edition, (Pearson Education, 2013). * - * @author Lee Boynton - * @author Arthur van Hoff - * @author Josh Bloch - * @author Joseph D. Darcy * @since 1.0 */ @jdk.internal.ValueBased diff --git a/src/java.base/share/classes/java/lang/Math.java b/src/java.base/share/classes/java/lang/Math.java index ef5d1214b11..0f39ecf0a8a 100644 --- a/src/java.base/share/classes/java/lang/Math.java +++ b/src/java.base/share/classes/java/lang/Math.java @@ -2529,7 +2529,6 @@ public final class Math { * * @param d the floating-point value whose ulp is to be returned * @return the size of an ulp of the argument - * @author Joseph D. Darcy * @since 1.5 */ public static double ulp(double d) { @@ -2576,7 +2575,6 @@ public final class Math { * * @param f the floating-point value whose ulp is to be returned * @return the size of an ulp of the argument - * @author Joseph D. Darcy * @since 1.5 */ public static float ulp(float f) { @@ -2617,7 +2615,6 @@ public final class Math { * * @param d the floating-point value whose signum is to be returned * @return the signum function of the argument - * @author Joseph D. Darcy * @since 1.5 */ @IntrinsicCandidate @@ -2639,7 +2636,6 @@ public final class Math { * * @param f the floating-point value whose signum is to be returned * @return the signum function of the argument - * @author Joseph D. Darcy * @since 1.5 */ @IntrinsicCandidate diff --git a/src/java.base/share/classes/java/lang/Short.java b/src/java.base/share/classes/java/lang/Short.java index f0ae8b28e45..4c64427b6df 100644 --- a/src/java.base/share/classes/java/lang/Short.java +++ b/src/java.base/share/classes/java/lang/Short.java @@ -55,8 +55,6 @@ import static java.lang.constant.ConstantDescs.DEFAULT_NAME; * use instances for synchronization, or unpredictable behavior may * occur. For example, in a future release, synchronization may fail. * - * @author Nakul Saraiya - * @author Joseph D. Darcy * @see java.lang.Number * @since 1.1 */ diff --git a/src/java.base/share/classes/java/lang/StrictMath.java b/src/java.base/share/classes/java/lang/StrictMath.java index 266d98e3947..499fce73aee 100644 --- a/src/java.base/share/classes/java/lang/StrictMath.java +++ b/src/java.base/share/classes/java/lang/StrictMath.java @@ -101,7 +101,6 @@ import jdk.internal.vm.annotation.IntrinsicCandidate; * @spec https://standards.ieee.org/ieee/754/6210/ * IEEE Standard for Floating-Point Arithmetic * - * @author Joseph D. Darcy * @since 1.3 */ public final class StrictMath { @@ -493,7 +492,6 @@ public final class StrictMath { * @param a a value. * @return the closest floating-point value to {@code a} that is * equal to a mathematical integer. - * @author Joseph D. Darcy */ public static double rint(double a) { /* @@ -2014,7 +2012,6 @@ public final class StrictMath { * * @param d the floating-point value whose ulp is to be returned * @return the size of an ulp of the argument - * @author Joseph D. Darcy * @since 1.5 */ public static double ulp(double d) { @@ -2041,7 +2038,6 @@ public final class StrictMath { * * @param f the floating-point value whose ulp is to be returned * @return the size of an ulp of the argument - * @author Joseph D. Darcy * @since 1.5 */ public static float ulp(float f) { @@ -2062,7 +2058,6 @@ public final class StrictMath { * * @param d the floating-point value whose signum is to be returned * @return the signum function of the argument - * @author Joseph D. Darcy * @since 1.5 */ public static double signum(double d) { @@ -2083,7 +2078,6 @@ public final class StrictMath { * * @param f the floating-point value whose signum is to be returned * @return the signum function of the argument - * @author Joseph D. Darcy * @since 1.5 */ public static float signum(float f) { diff --git a/src/java.base/share/classes/java/math/BigDecimal.java b/src/java.base/share/classes/java/math/BigDecimal.java index c24998344c1..199b6648cdd 100644 --- a/src/java.base/share/classes/java/math/BigDecimal.java +++ b/src/java.base/share/classes/java/math/BigDecimal.java @@ -327,10 +327,6 @@ import jdk.internal.vm.annotation.Stable; * @spec https://standards.ieee.org/ieee/754/6210/ * IEEE Standard for Floating-Point Arithmetic * - * @author Josh Bloch - * @author Mike Cowlishaw - * @author Joseph D. Darcy - * @author Sergey V. Kuksenko * @since 1.1 */ public class BigDecimal extends Number implements Comparable { @@ -1779,7 +1775,6 @@ public class BigDecimal extends Number implements Comparable { * terminating decimal expansion, including dividing by zero * @return {@code this / divisor} * @since 1.5 - * @author Joseph D. Darcy */ public BigDecimal divide(BigDecimal divisor) { /* @@ -1948,7 +1943,6 @@ public class BigDecimal extends Number implements Comparable { * @throws ArithmeticException if {@code mc.precision} {@literal >} 0 and the result * requires a precision of more than {@code mc.precision} digits. * @since 1.5 - * @author Joseph D. Darcy */ public BigDecimal divideToIntegralValue(BigDecimal divisor, MathContext mc) { if (mc.precision == 0 || // exact result diff --git a/src/java.base/share/classes/java/math/MathContext.java b/src/java.base/share/classes/java/math/MathContext.java index d0c1cb4a5a9..f80fcc3e076 100644 --- a/src/java.base/share/classes/java/math/MathContext.java +++ b/src/java.base/share/classes/java/math/MathContext.java @@ -51,8 +51,6 @@ import java.io.*; * @spec https://standards.ieee.org/ieee/754/6210/ * IEEE Standard for Floating-Point Arithmetic * - * @author Mike Cowlishaw - * @author Joseph D. Darcy * @since 1.5 */ diff --git a/src/java.base/share/classes/java/math/RoundingMode.java b/src/java.base/share/classes/java/math/RoundingMode.java index e66a64e143f..4188c781cab 100644 --- a/src/java.base/share/classes/java/math/RoundingMode.java +++ b/src/java.base/share/classes/java/math/RoundingMode.java @@ -115,9 +115,6 @@ package java.math; * IEEE Standard for Floating-Point Arithmetic * @jls 15.4 Floating-point Expressions * - * @author Josh Bloch - * @author Mike Cowlishaw - * @author Joseph D. Darcy * @since 1.5 */ @SuppressWarnings("deprecation") // Legacy rounding mode constants in BigDecimal diff --git a/src/java.base/share/classes/jdk/internal/math/DoubleConsts.java b/src/java.base/share/classes/jdk/internal/math/DoubleConsts.java index d3a271fdd07..168e99d4ef5 100644 --- a/src/java.base/share/classes/jdk/internal/math/DoubleConsts.java +++ b/src/java.base/share/classes/jdk/internal/math/DoubleConsts.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,8 +32,6 @@ import static java.lang.Double.SIZE; /** * This class contains additional constants documenting limits of the * {@code double} type. - * - * @author Joseph D. Darcy */ public class DoubleConsts { diff --git a/src/java.base/share/classes/jdk/internal/math/FloatConsts.java b/src/java.base/share/classes/jdk/internal/math/FloatConsts.java index fd304c7871a..2bd484e99f3 100644 --- a/src/java.base/share/classes/jdk/internal/math/FloatConsts.java +++ b/src/java.base/share/classes/jdk/internal/math/FloatConsts.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,8 +32,6 @@ import static java.lang.Float.SIZE; /** * This class contains additional constants documenting limits of the * {@code float} type. - * - * @author Joseph D. Darcy */ public class FloatConsts { From 49b17dd5c97bf967c01166542cfccf4b196cf8a9 Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Fri, 17 Oct 2025 22:58:26 +0000 Subject: [PATCH 0274/1639] 8356575: Test order in which jpackage fills app image Reviewed-by: almatvee --- .../internal/ApplicationImageUtils.java | 4 +- .../jpackage/test/LauncherIconVerifier.java | 3 +- .../helpers/jdk/jpackage/test/TKit.java | 30 ++ .../jpackage/share/AppImageFillOrderTest.java | 359 ++++++++++++++++++ 4 files changed, 393 insertions(+), 3 deletions(-) create mode 100644 test/jdk/tools/jpackage/share/AppImageFillOrderTest.java diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ApplicationImageUtils.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ApplicationImageUtils.java index 7d3250ff7b9..cda5b6c79ef 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ApplicationImageUtils.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/ApplicationImageUtils.java @@ -32,6 +32,7 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.Path; +import java.nio.file.StandardCopyOption; import java.util.ArrayList; import java.util.List; import java.util.Optional; @@ -148,6 +149,7 @@ final class ApplicationImageUtils { } } - FileUtils.copyRecursive(srcDir, dstDir.toAbsolutePath(), excludes, LinkOption.NOFOLLOW_LINKS); + FileUtils.copyRecursive(srcDir, dstDir.toAbsolutePath(), excludes, + LinkOption.NOFOLLOW_LINKS, StandardCopyOption.REPLACE_EXISTING); } } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherIconVerifier.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherIconVerifier.java index 6285d9d93a0..278cd569bac 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherIconVerifier.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherIconVerifier.java @@ -24,7 +24,6 @@ package jdk.jpackage.test; import java.io.IOException; -import java.nio.file.Files; import java.nio.file.Path; public final class LauncherIconVerifier { @@ -77,7 +76,7 @@ public final class LauncherIconVerifier { } else { TKit.assertFileExists(iconPath); if (!verifyFileInAppImageOnly) { - TKit.assertTrue(-1 == Files.mismatch(expectedIcon, iconPath), + TKit.assertSameFileContent(expectedIcon, iconPath, String.format( "Check icon file [%s] of %s launcher is a copy of source icon file [%s]", iconPath, label, expectedIcon)); diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java index b3f188bb371..ed9c727abcc 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java @@ -25,6 +25,7 @@ package jdk.jpackage.test; import static java.nio.file.StandardWatchEventKinds.ENTRY_CREATE; import static java.nio.file.StandardWatchEventKinds.ENTRY_MODIFY; import static java.util.stream.Collectors.toSet; +import static jdk.jpackage.internal.util.function.ThrowingBiFunction.toBiFunction; import static jdk.jpackage.internal.util.function.ThrowingSupplier.toSupplier; import java.io.Closeable; @@ -797,6 +798,35 @@ public final class TKit { } } + public static void assertMismatchFileContent(Path a, Path b) { + assertFilesMismatch(a, b, true, Optional.empty()); + } + + public static void assertMismatchFileContent(Path a, Path b, String msg) { + assertFilesMismatch(a, b, true, Optional.of(msg)); + } + + public static void assertSameFileContent(Path a, Path b) { + assertFilesMismatch(a, b, false, Optional.empty()); + } + + public static void assertSameFileContent(Path a, Path b, String msg) { + assertFilesMismatch(a, b, false, Optional.of(msg)); + } + + public static void assertFilesMismatch(Path a, Path b, boolean expectMismatch, Optional msg) { + var mismatch = toBiFunction(Files::mismatch).apply(a, b) != -1; + if (expectMismatch) { + assertTrue(mismatch, msg.orElseGet(() -> { + return String.format("Check the content of [%s] and [%s] files mismatch", a, b); + })); + } else { + assertTrue(!mismatch, msg.orElseGet(() -> { + return String.format("Check the content of [%s] and [%s] files is the same", a, b); + })); + } + } + public static void assertDirectoryNotEmpty(Path path) { assertDirectoryExists(path, Optional.of(false)); } diff --git a/test/jdk/tools/jpackage/share/AppImageFillOrderTest.java b/test/jdk/tools/jpackage/share/AppImageFillOrderTest.java new file mode 100644 index 00000000000..75c0ddfc16f --- /dev/null +++ b/test/jdk/tools/jpackage/share/AppImageFillOrderTest.java @@ -0,0 +1,359 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import static java.util.stream.Collectors.toMap; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.TreeMap; +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.stream.Stream; +import jdk.jpackage.test.Annotations.Parameter; +import jdk.jpackage.test.Annotations.ParameterSupplier; +import jdk.jpackage.test.Annotations.Test; +import jdk.jpackage.test.AppImageFile; +import jdk.jpackage.test.ApplicationLayout; +import jdk.jpackage.test.JPackageCommand; +import jdk.jpackage.test.TKit; + +/* + * @test + * @summary test order in which jpackage fills app image + * @library /test/jdk/tools/jpackage/helpers + * @build jdk.jpackage.test.* + * @compile -Xlint:all -Werror AppImageFillOrderTest.java + * @run main/othervm/timeout=1440 -Xmx512m + * jdk.jpackage.test.Main + * --jpt-run=AppImageFillOrderTest + */ + +/** + * Test order in which overlapping items are added to the app image. jpackage + * defaults should go first to let user-provided content override them. + * + *

    + * Custom content comes from: + *