From 6a9a867d645b8fe86f4ca2b04a43bf5aa8f9d487 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Thu, 8 Aug 2024 14:38:46 +0000 Subject: [PATCH 01/20] 8337994: [REDO] Native memory leak when not recording any events Reviewed-by: egahlin --- .../share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp | 9 +++++++++ .../share/jfr/recorder/service/jfrRecorderService.cpp | 6 +----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp index 203ec3a3ec494..279b871d8181a 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSet.cpp @@ -883,6 +883,15 @@ static void do_clds(CldWriter& cldw) { ModuleCldWriter mcw(&cldw); KlassAndModuleCldWriter kmcw(&kcw, &mcw); _artifacts->iterate_klasses(kmcw); + if (is_initial_typeset_for_chunk()) { + CldPtr bootloader = get_cld(Universe::boolArrayKlass()); + assert(bootloader != nullptr, "invariant"); + if (IS_NOT_SERIALIZED(bootloader)) { + write__cld(_writer, bootloader); + assert(IS_SERIALIZED(bootloader), "invariant"); + cldw.add(1); + } + } _artifacts->tally(cldw); } diff --git a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp index fc2043a4d921d..0395b711c6521 100644 --- a/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp +++ b/src/hotspot/share/jfr/recorder/service/jfrRecorderService.cpp @@ -639,11 +639,7 @@ static void write_thread_local_buffer(JfrChunkWriter& chunkwriter, Thread* t) { size_t JfrRecorderService::flush() { size_t total_elements = flush_metadata(_chunkwriter); - const size_t storage_elements = flush_storage(_storage, _chunkwriter); - if (0 == storage_elements) { - return total_elements; - } - total_elements += storage_elements; + total_elements = flush_storage(_storage, _chunkwriter); if (_string_pool.is_modified()) { total_elements += flush_stringpool(_string_pool, _chunkwriter); } From 78773b1769922611318243b6680d59518ed4e015 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Thu, 8 Aug 2024 15:52:17 +0000 Subject: [PATCH 02/20] 8338015: Fix "Java Java" typo in package info file of java.lang.classfile Reviewed-by: jiefu, jpai, liach --- .../share/classes/java/lang/classfile/package-info.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/lang/classfile/package-info.java b/src/java.base/share/classes/java/lang/classfile/package-info.java index b5991b0e951b9..921cf9e1a3443 100644 --- a/src/java.base/share/classes/java/lang/classfile/package-info.java +++ b/src/java.base/share/classes/java/lang/classfile/package-info.java @@ -26,8 +26,8 @@ /** *

Provides classfile parsing, generation, and transformation library.

* The {@code java.lang.classfile} package contains classes for reading, writing, and - * modifying Java class files, as specified in Chapter {@jvms 4} of the Java - * Java Virtual Machine Specification. + * modifying Java class files, as specified in Chapter {@jvms 4} of the + * Java Virtual Machine Specification. * *

Reading classfiles

* The main class for reading classfiles is {@link java.lang.classfile.ClassModel}; we From 9695f09581bac856ad97943cca15c65dc21d2adf Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Thu, 8 Aug 2024 16:11:08 +0000 Subject: [PATCH 03/20] 8337683: Fix -Wconversion problem with arrayOop.hpp Reviewed-by: stefank, dholmes --- src/hotspot/share/oops/arrayOop.hpp | 18 +++++++++--------- src/hotspot/share/runtime/atomic.hpp | 5 +++-- src/hotspot/share/utilities/byteswap.hpp | 3 ++- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/hotspot/share/oops/arrayOop.hpp b/src/hotspot/share/oops/arrayOop.hpp index 0aa26500bd8d2..1ca8a9530a48c 100644 --- a/src/hotspot/share/oops/arrayOop.hpp +++ b/src/hotspot/share/oops/arrayOop.hpp @@ -68,10 +68,10 @@ class arrayOopDesc : public oopDesc { // The header is considered the oop part of this type plus the length. // This is not equivalent to sizeof(arrayOopDesc) which should not appear in the code. static int header_size_in_bytes() { - size_t hs = length_offset_in_bytes() + sizeof(int); + int hs = length_offset_in_bytes() + (int)sizeof(int); #ifdef ASSERT // make sure it isn't called before UseCompressedOops is initialized. - static size_t arrayoopdesc_hs = 0; + static int arrayoopdesc_hs = 0; if (arrayoopdesc_hs == 0) arrayoopdesc_hs = hs; assert(arrayoopdesc_hs == hs, "header size can't change"); #endif // ASSERT @@ -83,13 +83,13 @@ class arrayOopDesc : public oopDesc { // it occupies the second half of the _klass field in oopDesc. static int length_offset_in_bytes() { return UseCompressedClassPointers ? klass_gap_offset_in_bytes() : - sizeof(arrayOopDesc); + (int)sizeof(arrayOopDesc); } // Returns the offset of the first element. static int base_offset_in_bytes(BasicType type) { - size_t hs = header_size_in_bytes(); - return (int)(element_type_should_be_aligned(type) ? align_up(hs, BytesPerLong) : hs); + int hs = header_size_in_bytes(); + return element_type_should_be_aligned(type) ? align_up(hs, BytesPerLong) : hs; } // Returns the address of the first element. The elements in the array will not @@ -134,14 +134,14 @@ class arrayOopDesc : public oopDesc { assert(type < T_CONFLICT, "wrong type"); assert(type2aelembytes(type) != 0, "wrong type"); - size_t hdr_size_in_bytes = base_offset_in_bytes(type); + int hdr_size_in_bytes = base_offset_in_bytes(type); // This is rounded-up and may overlap with the first array elements. - size_t hdr_size_in_words = align_up(hdr_size_in_bytes, HeapWordSize) / HeapWordSize; + int hdr_size_in_words = align_up(hdr_size_in_bytes, HeapWordSize) / HeapWordSize; const size_t max_element_words_per_size_t = - align_down((SIZE_MAX/HeapWordSize - hdr_size_in_words), MinObjAlignment); + align_down((SIZE_MAX/HeapWordSize - (size_t)hdr_size_in_words), MinObjAlignment); const size_t max_elements_per_size_t = - HeapWordSize * max_element_words_per_size_t / type2aelembytes(type); + HeapWordSize * max_element_words_per_size_t / (size_t)type2aelembytes(type); if ((size_t)max_jint < max_elements_per_size_t) { // It should be ok to return max_jint here, but parts of the code // (CollectedHeap, Klass::oop_oop_iterate(), and more) uses an int for diff --git a/src/hotspot/share/runtime/atomic.hpp b/src/hotspot/share/runtime/atomic.hpp index 399a78fd3fce1..bf198b5f5621f 100644 --- a/src/hotspot/share/runtime/atomic.hpp +++ b/src/hotspot/share/runtime/atomic.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ #include "runtime/orderAccess.hpp" #include "utilities/align.hpp" #include "utilities/bytes.hpp" +#include "utilities/checkedCast.hpp" #include "utilities/macros.hpp" #include @@ -1118,7 +1119,7 @@ inline T Atomic::CmpxchgByteUsingInt::operator()(T volatile* dest, uint8_t canon_compare_value = compare_value; volatile uint32_t* aligned_dest = reinterpret_cast(align_down(dest, sizeof(uint32_t))); - size_t offset = pointer_delta(dest, aligned_dest, 1); + uint32_t offset = checked_cast(pointer_delta(dest, aligned_dest, 1)); uint32_t idx = (Endian::NATIVE == Endian::BIG) ? (sizeof(uint32_t) - 1 - offset) diff --git a/src/hotspot/share/utilities/byteswap.hpp b/src/hotspot/share/utilities/byteswap.hpp index fba0775cf4992..9c3b53630b39b 100644 --- a/src/hotspot/share/utilities/byteswap.hpp +++ b/src/hotspot/share/utilities/byteswap.hpp @@ -26,6 +26,7 @@ #define SHARE_UTILITIES_BYTESWAP_HPP #include "metaprogramming/enableIf.hpp" +#include "utilities/checkedCast.hpp" #include "utilities/globalDefinitions.hpp" #include @@ -63,7 +64,7 @@ struct ByteswapFallbackImpl; template struct ByteswapFallbackImpl { inline constexpr uint16_t operator()(uint16_t x) const { - return (((x & UINT16_C(0x00ff)) << 8) | ((x & UINT16_C(0xff00)) >> 8)); + return checked_cast(((x & UINT16_C(0x00ff)) << 8) | ((x & UINT16_C(0xff00)) >> 8)); } }; From 53c9f037fb2805aab5ab9729166ce7d5bc7a77f9 Mon Sep 17 00:00:00 2001 From: Jiangli Zhou Date: Thu, 8 Aug 2024 16:31:02 +0000 Subject: [PATCH 04/20] 8336849: Remove .llvm_addrsig section from JDK/VM static libraries (.a files) Reviewed-by: ihse --- make/common/native/Link.gmk | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/make/common/native/Link.gmk b/make/common/native/Link.gmk index 2090218ffbb34..ca03c6ee6b12f 100644 --- a/make/common/native/Link.gmk +++ b/make/common/native/Link.gmk @@ -109,6 +109,11 @@ define CreateStaticLibrary $(if $$($1_LINK_OBJS_RELATIVE), $$(CD) $$(OUTPUTDIR) ; ) \ $$($1_LD) $(LDFLAGS_CXX_PARTIAL_LINKING) $$($1_SYSROOT_LDFLAGS) \ -o $$($1_TARGET_RELOCATABLE) $$($1_LD_OBJ_ARG)) + # 'ld -r' might invalidate the .llvm_addrsig section, and this will cause subsequent + # calls to lld (with '-Wl,--icf=safe') to fail when linking with this library, so + # remove that section. + $$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_objcopy_remove_llvm_addrsig_section, \ + $$($1_OBJCOPY) --remove-section=.llvm_addrsig $$($1_TARGET_RELOCATABLE)) endif $$(call ExecuteWithLog, $$($1_OBJECT_DIR)/$$($1_SAFE_NAME)_run_ar, \ $(if $$($1_LINK_OBJS_RELATIVE), $$(CD) $$(OUTPUTDIR) ; ) \ From bfb75b96266f4c5840e2edea13f9aa2c801518cf Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Thu, 8 Aug 2024 16:53:38 +0000 Subject: [PATCH 05/20] 8336926: jdk/internal/util/ReferencedKeyTest.java can fail with ConcurrentModificationException Reviewed-by: bpb, shade, dfuchs --- .../jdk/internal/util/ReferencedKeyMap.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/java.base/share/classes/jdk/internal/util/ReferencedKeyMap.java b/src/java.base/share/classes/jdk/internal/util/ReferencedKeyMap.java index 9c364cd781350..810d43ae38a3a 100644 --- a/src/java.base/share/classes/jdk/internal/util/ReferencedKeyMap.java +++ b/src/java.base/share/classes/jdk/internal/util/ReferencedKeyMap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 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 @@ -219,8 +219,14 @@ public boolean containsValue(Object value) { @Override public V get(Object key) { - Objects.requireNonNull(key, "key must not be null"); removeStaleReferences(); + return getNoCheckStale(key); + } + + // Internal get(key) without removing stale references that would modify the keyset. + // Use when iterating or streaming over the keys to avoid ConcurrentModificationException. + private V getNoCheckStale(Object key) { + Objects.requireNonNull(key, "key must not be null"); return map.get(lookupKey(key)); } @@ -291,7 +297,7 @@ public Collection values() { public Set> entrySet() { removeStaleReferences(); return filterKeySet() - .map(k -> new AbstractMap.SimpleEntry<>(k, get(k))) + .map(k -> new AbstractMap.SimpleEntry<>(k, getNoCheckStale(k))) .collect(Collectors.toSet()); } @@ -335,7 +341,7 @@ public V replace(K key, V value) { public String toString() { removeStaleReferences(); return filterKeySet() - .map(k -> k + "=" + get(k)) + .map(k -> k + "=" + getNoCheckStale(k)) .collect(Collectors.joining(", ", "{", "}")); } From e7a0b5b09bcfcd8b09667e51ec588e206f0652ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Thu, 8 Aug 2024 18:45:11 +0000 Subject: [PATCH 06/20] 8334780: Crash: assert(h_array_list.not_null()) failed: invariant Reviewed-by: egahlin, shade --- src/hotspot/share/jfr/support/jfrJdkJfrEvent.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/jfr/support/jfrJdkJfrEvent.cpp b/src/hotspot/share/jfr/support/jfrJdkJfrEvent.cpp index cd47630228931..0c2fb0206ecee 100644 --- a/src/hotspot/share/jfr/support/jfrJdkJfrEvent.cpp +++ b/src/hotspot/share/jfr/support/jfrJdkJfrEvent.cpp @@ -136,7 +136,9 @@ jobject JdkJfrEvent::get_all_klasses(TRAPS) { transform_klasses_to_local_jni_handles(event_subklasses, THREAD); Handle h_array_list(THREAD, new_java_util_arraylist(THREAD)); - assert(h_array_list.not_null(), "invariant"); + if (h_array_list.is_null()) { + return empty_java_util_arraylist; + } static const char add_method_name[] = "add"; static const char add_method_signature[] = "(Ljava/lang/Object;)Z"; From 9f08a01cb6ebb08f67749aabdff4efaedfaf3228 Mon Sep 17 00:00:00 2001 From: Leonid Mesnik Date: Thu, 8 Aug 2024 19:47:50 +0000 Subject: [PATCH 07/20] 8338010: WB_IsFrameDeoptimized miss ResourceMark Reviewed-by: dholmes, shade --- src/hotspot/share/prims/whitebox.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp index 6ee33a6107998..544eeabb5c212 100644 --- a/src/hotspot/share/prims/whitebox.cpp +++ b/src/hotspot/share/prims/whitebox.cpp @@ -799,6 +799,7 @@ WB_END WB_ENTRY(jboolean, WB_IsFrameDeoptimized(JNIEnv* env, jobject o, jint depth)) bool result = false; if (thread->has_last_Java_frame()) { + ResourceMark rm(THREAD); RegisterMap reg_map(thread, RegisterMap::UpdateMap::include, RegisterMap::ProcessFrames::include, From 55c509708e9b89a7609fd41b6e5a271f250bbacd Mon Sep 17 00:00:00 2001 From: Jiawei Tang Date: Fri, 9 Aug 2024 02:29:15 +0000 Subject: [PATCH 08/20] 8337331: crash: pinned virtual thread will lead to jvm crash when running with the javaagent option Reviewed-by: dholmes, sspitsyn --- src/hotspot/share/prims/jvmtiExport.cpp | 10 +-- .../TestPinCaseWithCFLH.java | 77 +++++++++++++++++++ 2 files changed, 82 insertions(+), 5 deletions(-) create mode 100644 test/hotspot/jtreg/serviceability/jvmti/vthread/TestPinCaseWithCFLH/TestPinCaseWithCFLH.java diff --git a/src/hotspot/share/prims/jvmtiExport.cpp b/src/hotspot/share/prims/jvmtiExport.cpp index f79116f5ebeb0..95cc54d93134f 100644 --- a/src/hotspot/share/prims/jvmtiExport.cpp +++ b/src/hotspot/share/prims/jvmtiExport.cpp @@ -929,9 +929,8 @@ class JvmtiClassFileLoadHookPoster : public StackObj { _cached_class_file_ptr = cache_ptr; _has_been_modified = false; - if (_thread->is_in_any_VTMS_transition()) { - return; // no events should be posted if thread is in any VTMS transition - } + assert(!_thread->is_in_any_VTMS_transition(), "CFLH events are not allowed in any VTMS transition"); + _state = JvmtiExport::get_jvmti_thread_state(_thread); if (_state != nullptr) { _class_being_redefined = _state->get_class_being_redefined(); @@ -1091,8 +1090,9 @@ bool JvmtiExport::post_class_file_load_hook(Symbol* h_name, if (JvmtiEnv::get_phase() < JVMTI_PHASE_PRIMORDIAL) { return false; } - if (JavaThread::current()->is_in_tmp_VTMS_transition()) { - return false; // skip CFLH events in tmp VTMS transition + + if (JavaThread::current()->is_in_any_VTMS_transition()) { + return false; // no events should be posted if thread is in any VTMS transition } JvmtiClassFileLoadHookPoster poster(h_name, class_loader, diff --git a/test/hotspot/jtreg/serviceability/jvmti/vthread/TestPinCaseWithCFLH/TestPinCaseWithCFLH.java b/test/hotspot/jtreg/serviceability/jvmti/vthread/TestPinCaseWithCFLH/TestPinCaseWithCFLH.java new file mode 100644 index 0000000000000..02755a0289fc1 --- /dev/null +++ b/test/hotspot/jtreg/serviceability/jvmti/vthread/TestPinCaseWithCFLH/TestPinCaseWithCFLH.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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.instrument.ClassFileTransformer; +import java.lang.instrument.IllegalClassFormatException; +import java.lang.instrument.Instrumentation; +import java.security.ProtectionDomain; +import jdk.test.lib.thread.VThreadPinner; + +/* + * @test + * @summary javaagent + tracePinnedThreads will cause jvm crash/ run into deadlock when the virtual thread is pinned + * @library /test/lib + * @requires vm.continuations + * @requires vm.jvmti + * @modules java.base/java.lang:+open + * @compile TestPinCaseWithCFLH.java + * @build jdk.test.lib.Utils + * @run driver jdk.test.lib.util.JavaAgentBuilder + * TestPinCaseWithCFLH TestPinCaseWithCFLH.jar + * @run main/othervm/timeout=100 -Djdk.virtualThreadScheduler.maxPoolSize=1 + * -Djdk.tracePinnedThreads=full --enable-native-access=ALL-UNNAMED + * -javaagent:TestPinCaseWithCFLH.jar TestPinCaseWithCFLH + */ +public class TestPinCaseWithCFLH { + + public static class TestClassFileTransformer implements ClassFileTransformer { + public byte[] transform(ClassLoader loader, String className, Class classBeingRedefined, + ProtectionDomain protectionDomain, byte[] classfileBuffer) + throws IllegalClassFormatException { + return classfileBuffer; + } + } + + // Called when agent is loaded at startup + public static void premain(String agentArgs, Instrumentation instrumentation) throws Exception { + instrumentation.addTransformer(new TestClassFileTransformer()); + } + + private static int result = 0; + + public static void main(String[] args) throws Exception{ + Thread t1 = Thread.ofVirtual().name("vthread-1").start(() -> { + VThreadPinner.runPinned(() -> { + try { + // try yield, will pin, + // javaagent + tracePinnedThreads should not lead to crash + // (because of the class `PinnedThreadPrinter`) + Thread.sleep(500); + } catch (Exception e) { + e.printStackTrace(); + } + }); + }); + t1.join(); + } + +} \ No newline at end of file From 0c1e9111d226b601236b9826e27ecc67a8b625fb Mon Sep 17 00:00:00 2001 From: Gui Cao Date: Fri, 9 Aug 2024 02:59:37 +0000 Subject: [PATCH 09/20] 8338019: Fix simple -Wzero-as-null-pointer-constant warnings in riscv code Reviewed-by: fyang, mli, luhenry --- src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp | 2 +- src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp | 2 +- src/hotspot/cpu/riscv/frame_riscv.cpp | 2 +- src/hotspot/cpu/riscv/nativeInst_riscv.cpp | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp index 798679185d3a2..3d146b87707aa 100644 --- a/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_riscv.cpp @@ -542,7 +542,7 @@ void LIR_Assembler::const2mem(LIR_Opr src, LIR_Opr dest, BasicType type, CodeEmi insn = &MacroAssembler::sw; break; case T_OBJECT: // fall through case T_ARRAY: - assert(c->as_jobject() == 0, "should be"); + assert(c->as_jobject() == nullptr, "should be"); if (UseCompressedOops && !wide) { insn = &MacroAssembler::sw; } else { diff --git a/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp b/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp index 9fa8939837a85..e999b703b3e7b 100644 --- a/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp +++ b/src/hotspot/cpu/riscv/c1_Runtime1_riscv.cpp @@ -1066,4 +1066,4 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { #undef __ -const char *Runtime1::pd_name_for_address(address entry) { Unimplemented(); return 0; } +const char *Runtime1::pd_name_for_address(address entry) { Unimplemented(); } diff --git a/src/hotspot/cpu/riscv/frame_riscv.cpp b/src/hotspot/cpu/riscv/frame_riscv.cpp index 32825a02c5eac..96dca4704ad95 100644 --- a/src/hotspot/cpu/riscv/frame_riscv.cpp +++ b/src/hotspot/cpu/riscv/frame_riscv.cpp @@ -269,7 +269,7 @@ void frame::patch_pc(Thread* thread, address pc) { // Either the return address is the original one or we are going to // patch in the same address that's already there. - assert(_pc == pc_old || pc == pc_old || pc_old == 0, "must be"); + assert(_pc == pc_old || pc == pc_old || pc_old == nullptr, "must be"); DEBUG_ONLY(address old_pc = _pc;) *pc_addr = pc; _pc = pc; // must be set before call to get_deopt_original_pc diff --git a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp index f0357f1cd3029..6c9e0986869b6 100644 --- a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp +++ b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp @@ -685,7 +685,7 @@ address NativeJump::jump_destination() const { // load // return -1 if jump to self or to 0 - if ((dest == (address) this) || dest == 0) { + if ((dest == (address) this) || dest == nullptr) { dest = (address) -1; } @@ -714,7 +714,7 @@ address NativeGeneralJump::jump_destination() const { // a general jump // return -1 if jump to self or to 0 - if ((dest == (address) this) || dest == 0) { + if ((dest == (address) this) || dest == nullptr) { dest = (address) -1; } From 9ab8c6b9ba90ffd12600a250c8704571e9feb78d Mon Sep 17 00:00:00 2001 From: Abhishek Kumar Date: Fri, 9 Aug 2024 05:09:27 +0000 Subject: [PATCH 10/20] 8335130: The test "javax/swing/plaf/synth/ComponentsOrientationSupport/5033822/bug5033822.java" fails because the background color of the tabs is displayed incorrectly. Reviewed-by: achung, psadhukhan --- .../sun/java/swing/plaf/gtk/GTKPainter.java | 34 ++++++++-------- .../swing/plaf/nimbus/SynthPainterImpl.java | 39 ++++++++++--------- .../swing/plaf/synth/SynthTabbedPaneUI.java | 8 +--- 3 files changed, 41 insertions(+), 40 deletions(-) diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java index 4787696a367eb..ea27a2a6e0d9b 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java @@ -935,25 +935,27 @@ public void paintTabbedPaneTabBackground(SynthContext context, Graphics g, int x, int y, int w, int h, int tabIndex) { - Region id = context.getRegion(); - int state = context.getComponentState(); - int gtkState = ((state & SynthConstants.SELECTED) != 0 ? - SynthConstants.ENABLED : SynthConstants.PRESSED); JTabbedPane pane = (JTabbedPane)context.getComponent(); - int placement = pane.getTabPlacement(); + if (UIManager.getBoolean("TabbedPane.tabsOpaque") || pane.isOpaque()) { + Region id = context.getRegion(); + int state = context.getComponentState(); + int gtkState = ((state & SynthConstants.SELECTED) != 0 ? + SynthConstants.ENABLED : SynthConstants.PRESSED); + int placement = pane.getTabPlacement(); - // Fill the tab rect area - g.fillRect(x, y, w, h); + // Fill the tab rect area + g.fillRect(x, y, w, h); - synchronized (UNIXToolkit.GTK_LOCK) { - if (! ENGINE.paintCachedImage(g, x, y, w, h, - id, gtkState, placement, tabIndex)) { - PositionType side = POSITIONS[placement - 1]; - ENGINE.startPainting(g, x, y, w, h, - id, gtkState, placement, tabIndex); - ENGINE.paintExtension(g, context, id, gtkState, - ShadowType.OUT, "tab", x, y, w, h, side, tabIndex); - ENGINE.finishPainting(); + synchronized (UNIXToolkit.GTK_LOCK) { + if (!ENGINE.paintCachedImage(g, x, y, w, h, + id, gtkState, placement, tabIndex)) { + PositionType side = POSITIONS[placement - 1]; + ENGINE.startPainting(g, x, y, w, h, + id, gtkState, placement, tabIndex); + ENGINE.paintExtension(g, context, id, gtkState, + ShadowType.OUT, "tab", x, y, w, h, side, tabIndex); + ENGINE.finishPainting(); + } } } } diff --git a/src/java.desktop/share/classes/javax/swing/plaf/nimbus/SynthPainterImpl.java b/src/java.desktop/share/classes/javax/swing/plaf/nimbus/SynthPainterImpl.java index c990c968ff6fa..9dfd422f6dddb 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/nimbus/SynthPainterImpl.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/nimbus/SynthPainterImpl.java @@ -2098,24 +2098,27 @@ public void paintTabbedPaneTabBackground(SynthContext context, Graphics g, public void paintTabbedPaneTabBackground(SynthContext context, Graphics g, int x, int y, int w, int h, int tabIndex, int orientation) { - if (orientation == JTabbedPane.LEFT) { - AffineTransform transform = new AffineTransform(); - transform.scale(-1, 1); - transform.rotate(Math.toRadians(90)); - paintBackground(context, g, y, x, h, w, transform); - } else if (orientation == JTabbedPane.RIGHT) { - AffineTransform transform = new AffineTransform(); - transform.rotate(Math.toRadians(90)); - transform.translate(0, -(x + w)); - paintBackground(context, g, y, 0, h, w, transform); - } else if (orientation == JTabbedPane.BOTTOM) { - AffineTransform transform = new AffineTransform(); - transform.translate(x,y); - transform.scale(1, -1); - transform.translate(0,-h); - paintBackground(context, g, 0, 0, w, h, transform); - } else { - paintBackground(context, g, x, y, w, h, null); + JTabbedPane pane = (JTabbedPane)context.getComponent(); + if (UIManager.getBoolean("TabbedPane.tabsOpaque") || pane.isOpaque()) { + if (orientation == JTabbedPane.LEFT) { + AffineTransform transform = new AffineTransform(); + transform.scale(-1, 1); + transform.rotate(Math.toRadians(90)); + paintBackground(context, g, y, x, h, w, transform); + } else if (orientation == JTabbedPane.RIGHT) { + AffineTransform transform = new AffineTransform(); + transform.rotate(Math.toRadians(90)); + transform.translate(0, -(x + w)); + paintBackground(context, g, y, 0, h, w, transform); + } else if (orientation == JTabbedPane.BOTTOM) { + AffineTransform transform = new AffineTransform(); + transform.translate(x, y); + transform.scale(1, -1); + transform.translate(0, -h); + paintBackground(context, g, 0, 0, w, h, transform); + } else { + paintBackground(context, g, x, y, w, h, null); + } } } diff --git a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTabbedPaneUI.java b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTabbedPaneUI.java index 837c4d8298f9e..3378ef9e8b3de 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTabbedPaneUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTabbedPaneUI.java @@ -127,7 +127,6 @@ public class SynthTabbedPaneUI extends BasicTabbedPaneUI // Background color for unselected tabs private Color unselectedBackground; private boolean contentOpaque = true; - private boolean tabsOpaque = true; /** * @@ -156,7 +155,6 @@ private boolean scrollableTabLayoutEnabled() { protected void installDefaults() { selectColor = UIManager.getColor("TabbedPane.selected"); contentOpaque = UIManager.getBoolean("TabbedPane.contentOpaque"); - tabsOpaque = UIManager.getBoolean("TabbedPane.tabsOpaque"); unselectedBackground = UIManager.getColor("TabbedPane.unselectedBackground"); updateStyle(tabPane); } @@ -655,10 +653,8 @@ private void paintTab(SynthContext ss, Graphics g, g.setColor(getUnselectedBackgroundAt(tabIndex)); } - if (tabsOpaque || tabPane.isOpaque()) { - tabContext.getPainter().paintTabbedPaneTabBackground(tabContext, g, - x, y, width, height, tabIndex, placement); - } + tabContext.getPainter().paintTabbedPaneTabBackground(tabContext, g, + x, y, width, height, tabIndex, placement); tabContext.getPainter().paintTabbedPaneTabBorder(tabContext, g, x, y, width, height, tabIndex, placement); From 00aac4097abd3c5e6144734cfd44228bc31892fb Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Fri, 9 Aug 2024 06:26:22 +0000 Subject: [PATCH 11/20] 8338058: map_or_reserve_memory_aligned Windows enhance remap assertion Reviewed-by: mdoerr, clanger --- src/hotspot/os/windows/os_windows.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 1cc7d9aa33adf..65ba13b0d9e81 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -3463,6 +3463,7 @@ static char* map_or_reserve_memory_aligned(size_t size, size_t alignment, int fi } assert(aligned_base != nullptr, "Did not manage to re-map after %d attempts?", max_attempts); + assert(aligned_base != nullptr, "Did not manage to re-map after %d attempts (size %zu, alignment %zu, file descriptor %d)", max_attempts, size, alignment, file_desc); return aligned_base; } From c01f53ac2dab1d4d2cd1e4d45a67f9373d4a9c7e Mon Sep 17 00:00:00 2001 From: Christian Hagedorn Date: Fri, 9 Aug 2024 07:17:59 +0000 Subject: [PATCH 12/20] 8337876: [IR Framework] Add support for IR tests with @Stable Reviewed-by: shade, kvn --- .../jtreg/compiler/lib/ir_framework/README.md | 11 ++- .../lib/ir_framework/TestFramework.java | 13 +++- .../ir_framework/driver/TestVMProcess.java | 15 ++-- .../tests/TestPhaseIRMatching.java | 2 +- .../tests/TestPrivilegedMode.java | 69 +++++++++++++++++++ 5 files changed, 103 insertions(+), 7 deletions(-) create mode 100644 test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPrivilegedMode.java diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/README.md b/test/hotspot/jtreg/compiler/lib/ir_framework/README.md index 3f6e0d4163faa..55d9fcbaecead 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/README.md +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/README.md @@ -157,7 +157,16 @@ The framework allows the use of additional compiler control annotations for help - [@ForceCompile](./ForceCompile.java) - [@ForceCompileClassInitializer](./ForceCompileClassInitializer.java) -### 2.5 Framework Debug and Stress Flags +### 2.5 IR Tests with Privileged Classes +To run tests in a privileged mode (e.g. when using `@Stable`, `@Contended`, `@ReservedStackAccess` etc.), one need to add the test classes to the boot classpath. This can easily be achieved by calling `TestFramework.addTestClassesToBootClassPath()` on the test framework object: +``` +TestFramework testFramework = new TestFramework(); +testFramework + .addTestClassesToBootClassPath() + .start(); +``` + +### 2.6 Framework Debug and Stress Flags The framework provides various stress and debug flags. They should mainly be used as JTreg VM and/or Javaoptions (apart from `VerifyIR`). The following (property) flags are supported: - `-DVerifyIR=false`: Explicitly disable IR verification. This is useful, for example, if some scenarios use VM flags that let `@IR` annotation rules fail and the user does not want to provide separate IR rules or add flag preconditions to the already existing IR rules. diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java index 67fadbc4eac31..d477aa44763fa 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java @@ -172,6 +172,7 @@ public class TestFramework { private Set scenarioIndices; private List flags; private int defaultWarmup = -1; + private boolean testClassesOnBootClassPath; /* * Public interface methods @@ -323,6 +324,15 @@ public TestFramework addScenarios(Scenario... scenarios) { return this; } + /** + * Add test classes to boot classpath. This adds all classes found on path {@link jdk.test.lib.Utils#TEST_CLASSES} + * to the boot classpath with "-Xbootclasspath/a". This is useful when trying to run tests in a privileged mode. + */ + public TestFramework addTestClassesToBootClassPath() { + this.testClassesOnBootClassPath = true; + return this; + } + /** * Start the testing of the implicitly (by {@link #TestFramework()}) or explicitly (by {@link #TestFramework(Class)}) * set test class. @@ -744,7 +754,8 @@ private boolean onlyWhitelistedJTregVMAndJavaOptsFlags() { } private void runTestVM(List additionalFlags) { - TestVMProcess testVMProcess = new TestVMProcess(additionalFlags, testClass, helperClasses, defaultWarmup); + TestVMProcess testVMProcess = new TestVMProcess(additionalFlags, testClass, helperClasses, defaultWarmup, + testClassesOnBootClassPath); if (shouldVerifyIR) { try { TestClassParser testClassParser = new TestClassParser(testClass); diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/TestVMProcess.java b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/TestVMProcess.java index 04f8096d96917..8c168b73260cf 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/driver/TestVMProcess.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/driver/TestVMProcess.java @@ -34,6 +34,7 @@ import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; +import java.io.File; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -63,11 +64,12 @@ public class TestVMProcess { private OutputAnalyzer oa; private String irEncoding; - public TestVMProcess(List additionalFlags, Class testClass, Set> helperClasses, int defaultWarmup) { + public TestVMProcess(List additionalFlags, Class testClass, Set> helperClasses, int defaultWarmup, + boolean testClassesOnBootClassPath) { this.cmds = new ArrayList<>(); TestFrameworkSocket socket = new TestFrameworkSocket(); try (socket) { - prepareTestVMFlags(additionalFlags, socket, testClass, helperClasses, defaultWarmup); + prepareTestVMFlags(additionalFlags, socket, testClass, helperClasses, defaultWarmup, testClassesOnBootClassPath); start(); } processSocketOutput(socket); @@ -91,11 +93,16 @@ public static String getLastTestVMOutput() { } private void prepareTestVMFlags(List additionalFlags, TestFrameworkSocket socket, Class testClass, - Set> helperClasses, int defaultWarmup) { + Set> helperClasses, int defaultWarmup, boolean testClassesOnBootClassPath) { // Set java.library.path so JNI tests which rely on jtreg nativepath setting work cmds.add("-Djava.library.path=" + Utils.TEST_NATIVE_PATH); // Need White Box access in test VM. - cmds.add("-Xbootclasspath/a:."); + String bootClassPath = "-Xbootclasspath/a:."; + if (testClassesOnBootClassPath) { + // Add test classes themselves to boot classpath to make them privileged. + bootClassPath += File.pathSeparator + Utils.TEST_CLASSES; + } + cmds.add(bootClassPath); cmds.add("-XX:+UnlockDiagnosticVMOptions"); cmds.add("-XX:+WhiteBoxAPI"); // Ignore CompileCommand flags which have an impact on the profiling information. diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPhaseIRMatching.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPhaseIRMatching.java index 9a39fb5310f35..f0056ebc79da9 100644 --- a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPhaseIRMatching.java +++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPhaseIRMatching.java @@ -66,7 +66,7 @@ private static void run(Class testClass) { List noAdditionalFlags = new ArrayList<>(); FlagVMProcess flagVMProcess = new FlagVMProcess(testClass, noAdditionalFlags); List testVMFlags = flagVMProcess.getTestVMFlags(); - TestVMProcess testVMProcess = new TestVMProcess(testVMFlags, testClass, null, -1); + TestVMProcess testVMProcess = new TestVMProcess(testVMFlags, testClass, null, -1, false); TestClassParser testClassParser = new TestClassParser(testClass); Matchable testClassMatchable = testClassParser.parse(testVMProcess.getHotspotPidFileName(), testVMProcess.getIrEncoding()); diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPrivilegedMode.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPrivilegedMode.java new file mode 100644 index 0000000000000..347b2eb39fbfc --- /dev/null +++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestPrivilegedMode.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 ir_framework.tests; + +import compiler.lib.ir_framework.*; +import compiler.lib.ir_framework.driver.irmatching.IRViolationException; + +import jdk.internal.vm.annotation.Stable; +import jdk.test.lib.Asserts; + +/* + * @test + * @requires vm.flagless + * @summary Test that IR framework successfully adds test class to boot classpath in order to run in privileged mode. + * @modules java.base/jdk.internal.vm.annotation + * @library /test/lib / + * @run driver ir_framework.tests.TestPrivilegedMode + */ + +public class TestPrivilegedMode { + static @Stable int iFld; // Treated as constant after first being set. + + public static void main(String[] args) { + try { + TestFramework.run(); + Asserts.fail("should not reach"); + } catch (IRViolationException e) { + // Without adding test class to boot classpath, we fail to replace the field load by a constant. + Asserts.assertTrue(e.getExceptionInfo().contains("Matched forbidden node")); + Asserts.assertTrue(e.getExceptionInfo().contains("LoadI")); + } + + // When adding the test class to the boot classpath, we can replace the field load by a constant. + new TestFramework().addTestClassesToBootClassPath().start(); + } + + @Test + @Arguments(setup = "setup") + @IR(failOn = IRNode.LOAD_I) + public int test() { + return iFld; + } + + @Setup + public void setup() { + iFld = 34; + } +} From 82d5768c1bdccfaf97a41f32a8bfcfd03a0fb378 Mon Sep 17 00:00:00 2001 From: Andrey Turbanov Date: Fri, 9 Aug 2024 07:20:01 +0000 Subject: [PATCH 13/20] 8337840: Remove redundant null check in ObjectOutputStream.writeProxyDesc Reviewed-by: rriggs --- src/java.base/share/classes/java/io/ObjectOutputStream.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/io/ObjectOutputStream.java b/src/java.base/share/classes/java/io/ObjectOutputStream.java index 2dcf174cf5399..3650b10135356 100644 --- a/src/java.base/share/classes/java/io/ObjectOutputStream.java +++ b/src/java.base/share/classes/java/io/ObjectOutputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1272,7 +1272,7 @@ private void writeProxyDesc(ObjectStreamClass desc, boolean unshared) } bout.setBlockDataMode(true); - if (cl != null && isCustomSubclass()) { + if (isCustomSubclass()) { ReflectUtil.checkPackageAccess(cl); } annotateProxyClass(cl); From f74109bd178c92a9dff1ca6fce03b25f51a0384f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Sikstr=C3=B6m?= Date: Fri, 9 Aug 2024 07:29:56 +0000 Subject: [PATCH 14/20] 8337939: ZGC: Make assertions and checks less convoluted and explicit Reviewed-by: stefank, ayang, eosterlund --- src/hotspot/share/gc/z/zAddress.cpp | 6 ++-- src/hotspot/share/gc/z/zAddress.inline.hpp | 30 +++++++++++++++---- src/hotspot/share/gc/z/zBarrier.inline.hpp | 6 ++-- src/hotspot/share/gc/z/zBarrierSet.inline.hpp | 4 +-- src/hotspot/share/gc/z/zHeapIterator.cpp | 2 +- src/hotspot/share/gc/z/zMark.cpp | 4 +-- src/hotspot/share/gc/z/zMark.inline.hpp | 4 +-- src/hotspot/share/gc/z/zPage.inline.hpp | 2 +- .../share/gc/z/zReferenceProcessor.cpp | 4 +-- src/hotspot/share/gc/z/zVerify.cpp | 24 +++++++++------ 10 files changed, 55 insertions(+), 31 deletions(-) diff --git a/src/hotspot/share/gc/z/zAddress.cpp b/src/hotspot/share/gc/z/zAddress.cpp index d1c199fad070c..1cd33e44a05d1 100644 --- a/src/hotspot/share/gc/z/zAddress.cpp +++ b/src/hotspot/share/gc/z/zAddress.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -93,9 +93,7 @@ static void initialize_check_oop_function() { #ifdef CHECK_UNHANDLED_OOPS if (ZVerifyOops) { // Enable extra verification of usages of oops in oopsHierarchy.hpp - check_oop_function = [](oopDesc* obj) { - (void)to_zaddress(obj); - }; + check_oop_function = &check_is_valid_zaddress; } #endif } diff --git a/src/hotspot/share/gc/z/zAddress.inline.hpp b/src/hotspot/share/gc/z/zAddress.inline.hpp index 4adbf50bc86c6..bbc92a7e2aaf3 100644 --- a/src/hotspot/share/gc/z/zAddress.inline.hpp +++ b/src/hotspot/share/gc/z/zAddress.inline.hpp @@ -333,10 +333,22 @@ inline void dereferenceable_test(zaddress addr) { } #endif -inline zaddress to_zaddress(uintptr_t value) { - const zaddress addr = zaddress(value); +inline void check_is_valid_zaddress(zaddress addr) { assert_is_valid(addr); DEBUG_ONLY(dereferenceable_test(addr)); +} + +inline void check_is_valid_zaddress(uintptr_t value) { + check_is_valid_zaddress(zaddress(value)); +} + +inline void check_is_valid_zaddress(oopDesc* o) { + check_is_valid_zaddress(uintptr_t(o)); +} + +inline zaddress to_zaddress(uintptr_t value) { + const zaddress addr = zaddress(value); + check_is_valid_zaddress(addr); return addr; } @@ -344,7 +356,7 @@ inline zaddress to_zaddress(oopDesc* o) { return to_zaddress(uintptr_t(o)); } -inline oop to_oop(zaddress addr) { +inline void assert_is_oop_or_null(zaddress addr) { const oop obj = cast_to_oop(addr); assert(!ZVerifyOops || oopDesc::is_oop_or_null(obj), "Broken oop: " PTR_FORMAT " [" PTR_FORMAT " " PTR_FORMAT " " PTR_FORMAT " " PTR_FORMAT "]", p2i(obj), @@ -352,7 +364,16 @@ inline oop to_oop(zaddress addr) { *(uintptr_t*)(untype(addr) + 0x08), *(uintptr_t*)(untype(addr) + 0x10), *(uintptr_t*)(untype(addr) + 0x18)); - return obj; +} + +inline void assert_is_oop(zaddress addr) { + assert(!is_null(addr), "Should not be null"); + assert_is_oop_or_null(addr); +} + +inline oop to_oop(zaddress addr) { + assert_is_oop_or_null(addr); + return cast_to_oop(addr); } inline zaddress operator+(zaddress addr, size_t size) { @@ -378,7 +399,6 @@ inline void assert_is_valid(zaddress_unsafe addr) { DEBUG_ONLY(is_valid(addr, true /* assert_on_failure */);) } - inline uintptr_t untype(zaddress_unsafe addr) { return static_cast(addr); } diff --git a/src/hotspot/share/gc/z/zBarrier.inline.hpp b/src/hotspot/share/gc/z/zBarrier.inline.hpp index b3191e9ae3f7a..a3eb7a9ca67d6 100644 --- a/src/hotspot/share/gc/z/zBarrier.inline.hpp +++ b/src/hotspot/share/gc/z/zBarrier.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -745,7 +745,7 @@ inline void ZBarrier::mark_and_remember(volatile zpointer* p, zaddress addr) { template inline void ZBarrier::mark(zaddress addr) { - assert(!ZVerifyOops || oopDesc::is_oop(to_oop(addr), false), "must be oop"); + assert_is_oop(addr); if (ZHeap::heap()->is_old(addr)) { ZGeneration::old()->mark_object_if_active(addr); @@ -757,7 +757,7 @@ inline void ZBarrier::mark(zaddress addr) { template inline void ZBarrier::mark_young(zaddress addr) { assert(ZGeneration::young()->is_phase_mark(), "Should only be called during marking"); - assert(!ZVerifyOops || oopDesc::is_oop(to_oop(addr), false), "must be oop"); + assert_is_oop(addr); assert(ZHeap::heap()->is_young(addr), "Must be young"); ZGeneration::young()->mark_object(addr); diff --git a/src/hotspot/share/gc/z/zBarrierSet.inline.hpp b/src/hotspot/share/gc/z/zBarrierSet.inline.hpp index d53b69345dd98..174cdfd9e909d 100644 --- a/src/hotspot/share/gc/z/zBarrierSet.inline.hpp +++ b/src/hotspot/share/gc/z/zBarrierSet.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -430,7 +430,7 @@ class ZLoadBarrierOopClosure : public BasicOopIterateClosure { template inline void ZBarrierSet::AccessBarrier::clone_in_heap(oop src, oop dst, size_t size) { - assert_is_valid(to_zaddress(src)); + check_is_valid_zaddress(src); if (dst->is_objArray()) { // Cloning an object array is similar to performing array copy. diff --git a/src/hotspot/share/gc/z/zHeapIterator.cpp b/src/hotspot/share/gc/z/zHeapIterator.cpp index 50fc921131fe7..e149a976add92 100644 --- a/src/hotspot/share/gc/z/zHeapIterator.cpp +++ b/src/hotspot/share/gc/z/zHeapIterator.cpp @@ -146,7 +146,7 @@ class ZHeapIteratorUncoloredRootOopClosure : public OopClosure { oop load_oop(oop* p) { const oop o = Atomic::load(p); - assert_is_valid(to_zaddress(o)); + check_is_valid_zaddress(o); return RawAccess<>::oop_load(p); } diff --git a/src/hotspot/share/gc/z/zMark.cpp b/src/hotspot/share/gc/z/zMark.cpp index eb342495f5799..d33b86c83e57c 100644 --- a/src/hotspot/share/gc/z/zMark.cpp +++ b/src/hotspot/share/gc/z/zMark.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -365,7 +365,7 @@ void ZMark::follow_array_object(objArrayOop obj, bool finalizable) { } // Should be convertible to colorless oop - assert_is_valid(to_zaddress(obj)); + check_is_valid_zaddress(obj); zpointer* const addr = (zpointer*)obj->base(); const size_t length = (size_t)obj->length(); diff --git a/src/hotspot/share/gc/z/zMark.inline.hpp b/src/hotspot/share/gc/z/zMark.inline.hpp index b530259361027..9edc57a60002e 100644 --- a/src/hotspot/share/gc/z/zMark.inline.hpp +++ b/src/hotspot/share/gc/z/zMark.inline.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,7 +47,7 @@ template inline void ZMark::mark_object(zaddress addr) { - assert(!ZVerifyOops || oopDesc::is_oop(to_oop(addr)), "Should be oop"); + assert_is_oop(addr); ZPage* const page = _page_table->get(addr); if (page->is_allocating()) { diff --git a/src/hotspot/share/gc/z/zPage.inline.hpp b/src/hotspot/share/gc/z/zPage.inline.hpp index fcf69c685f7b6..d8ecad571907c 100644 --- a/src/hotspot/share/gc/z/zPage.inline.hpp +++ b/src/hotspot/share/gc/z/zPage.inline.hpp @@ -311,7 +311,7 @@ inline bool ZPage::mark_object(zaddress addr, bool finalizable, bool& inc_live) assert(is_in(addr), "Invalid address"); // Verify oop - (void)to_oop(addr); + assert_is_oop(addr); // Set mark bit const BitMap::idx_t index = bit_index(addr); diff --git a/src/hotspot/share/gc/z/zReferenceProcessor.cpp b/src/hotspot/share/gc/z/zReferenceProcessor.cpp index df8cb2b0e959f..1252de2ac2723 100644 --- a/src/hotspot/share/gc/z/zReferenceProcessor.cpp +++ b/src/hotspot/share/gc/z/zReferenceProcessor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -143,7 +143,7 @@ bool ZReferenceProcessor::is_inactive(zaddress reference, oop referent, Referenc return !is_null(reference_next(reference)); } else { // Verification - (void)to_zaddress(referent); + check_is_valid_zaddress(referent); // A non-FinalReference is inactive if the referent is null. The referent can only // be null if the application called Reference.enqueue() or Reference.clear(). diff --git a/src/hotspot/share/gc/z/zVerify.cpp b/src/hotspot/share/gc/z/zVerify.cpp index d47886ec7c2fc..b735965e9d49b 100644 --- a/src/hotspot/share/gc/z/zVerify.cpp +++ b/src/hotspot/share/gc/z/zVerify.cpp @@ -111,6 +111,16 @@ static bool z_is_null_relaxed(zpointer o) { return (untype(o) & ~color_mask) == 0; } +static void z_verify_oop_object(zaddress addr, zpointer o, void* p) { + const oop obj = cast_to_oop(addr); + guarantee(oopDesc::is_oop(obj), BAD_OOP_ARG(o, p)); +} + +static void z_verify_root_oop_object(zaddress addr, void* p) { + const oop obj = cast_to_oop(addr); + guarantee(oopDesc::is_oop(obj), BAD_OOP_ARG(addr, p)); +} + static void z_verify_old_oop(zpointer* p) { const zpointer o = *p; assert(o != zpointer::null, "Old should not contain raw null"); @@ -121,7 +131,7 @@ static void z_verify_old_oop(zpointer* p) { // safepoint after reference processing, where we hold the driver lock and // know there is no concurrent remembered set processing in the young generation. const zaddress addr = ZPointer::uncolor(o); - guarantee(oopDesc::is_oop(to_oop(addr)), BAD_OOP_ARG(o, p)); + z_verify_oop_object(addr, o, p); } else { const zaddress addr = ZBarrier::load_barrier_on_oop_field_preloaded(nullptr, o); // Old to young pointers might not be mark good if the young @@ -143,15 +153,11 @@ static void z_verify_young_oop(zpointer* p) { guarantee(ZPointer::is_marked_young(o), BAD_OOP_ARG(o, p)); if (ZPointer::is_load_good(o)) { - guarantee(oopDesc::is_oop(to_oop(ZPointer::uncolor(o))), BAD_OOP_ARG(o, p)); + z_verify_oop_object(ZPointer::uncolor(o), o, p); } } } -static void z_verify_root_oop_object(zaddress o, void* p) { - guarantee(oopDesc::is_oop(to_oop(o)), BAD_OOP_ARG(o, p)); -} - static void z_verify_uncolored_root_oop(zaddress* p) { assert(!ZHeap::heap()->is_in((uintptr_t)p), "Roots shouldn't be in heap"); const zaddress o = *p; @@ -168,7 +174,7 @@ static void z_verify_possibly_weak_oop(zpointer* p) { const zaddress addr = ZBarrier::load_barrier_on_oop_field_preloaded(nullptr, o); guarantee(ZHeap::heap()->is_old(addr) || ZPointer::is_marked_young(o), BAD_OOP_ARG(o, p)); guarantee(ZHeap::heap()->is_young(addr) || ZHeap::heap()->is_object_live(addr), BAD_OOP_ARG(o, p)); - guarantee(oopDesc::is_oop(to_oop(addr)), BAD_OOP_ARG(o, p)); + z_verify_oop_object(addr, o, p); // Verify no missing remset entries. We are holding the driver lock here and that // allows us to more precisely verify the remembered set, as there is no concurrent @@ -211,14 +217,14 @@ class ZVerifyColoredRootClosure : public OopClosure { // Minor collections could have relocated the object; // use load barrier to find correct object. const zaddress addr = ZBarrier::load_barrier_on_oop_field_preloaded(nullptr, o); - z_verify_root_oop_object(addr, p); + z_verify_oop_object(addr, o, p); } else { // Don't know the state of the oop if (is_valid(o)) { // it looks like a valid colored oop; // use load barrier to find correct object. const zaddress addr = ZBarrier::load_barrier_on_oop_field_preloaded(nullptr, o); - z_verify_root_oop_object(addr, p); + z_verify_oop_object(addr, o, p); } } } From 53fce38a3ff8700fef640fffc066efc21ff9c25f Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Fri, 9 Aug 2024 07:53:15 +0000 Subject: [PATCH 15/20] 8338062: JFR: Remove TestStartDuration.java and TestStartName.java from ProblemList.txt Reviewed-by: mgronlun --- test/jdk/ProblemList.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 8aedbc7793116..293d9d108d32c 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -745,8 +745,6 @@ jdk/incubator/vector/LoadJsvmlTest.java 8305390 windows- # jdk_jfr jdk/jfr/event/runtime/TestResidentSetSizeEvent.java 8309846 aix-ppc64 -jdk/jfr/startupargs/TestStartName.java 8214685 windows-x64 -jdk/jfr/startupargs/TestStartDuration.java 8214685 windows-x64 jdk/jfr/jvm/TestWaste.java 8282427 generic-all ############################################################################ From 6ebd5d74d57b334e7cf0b1282d7bb469a56fb3d6 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Fri, 9 Aug 2024 08:23:44 +0000 Subject: [PATCH 16/20] 8338036: Serial: Remove Generation::update_counters Reviewed-by: kbarrett --- src/hotspot/share/gc/serial/generation.hpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/hotspot/share/gc/serial/generation.hpp b/src/hotspot/share/gc/serial/generation.hpp index beb29928f4826..c6a9f94a8703a 100644 --- a/src/hotspot/share/gc/serial/generation.hpp +++ b/src/hotspot/share/gc/serial/generation.hpp @@ -114,8 +114,7 @@ class Generation: public CHeapObj { public: // Performance Counter support - virtual void update_counters() = 0; - virtual CollectorCounters* counters() { return _gc_counters; } + CollectorCounters* counters() { return _gc_counters; } GCMemoryManager* gc_manager() const { assert(_gc_manager != nullptr, "not initialized yet"); From c37e8638c98cb4516569304e9a0ab477affb0641 Mon Sep 17 00:00:00 2001 From: Hamlin Li Date: Fri, 9 Aug 2024 09:12:41 +0000 Subject: [PATCH 17/20] 8314125: RISC-V: implement Base64 intrinsic - encoding Reviewed-by: fyang, luhenry --- src/hotspot/cpu/riscv/assembler_riscv.hpp | 13 + src/hotspot/cpu/riscv/stubGenerator_riscv.cpp | 223 ++++++++++++++++++ src/hotspot/cpu/riscv/vm_version_riscv.cpp | 5 + 3 files changed, 241 insertions(+) diff --git a/src/hotspot/cpu/riscv/assembler_riscv.hpp b/src/hotspot/cpu/riscv/assembler_riscv.hpp index e4280ab34e1ce..79279be7acc1b 100644 --- a/src/hotspot/cpu/riscv/assembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/assembler_riscv.hpp @@ -1828,6 +1828,19 @@ enum Nf { #undef INSN +#define INSN(NAME, op, width, umop, mop, mew, nf) \ + void NAME(VectorRegister Vd_or_Vs3, Register Rs1, VectorMask vm = unmasked) { \ + patch_VLdSt(op, Vd_or_Vs3, width, Rs1, umop, vm, mop, mew, nf); \ + } + + // Vector Unit-Stride Segment Load Instructions + INSN(vlseg3e8_v, 0b0000111, 0b000, 0b00000, 0b00, 0b0, g3); + + // Vector Unit-Stride Segment Store Instructions + INSN(vsseg4e8_v, 0b0100111, 0b000, 0b00000, 0b00, 0b0, g4); + +#undef INSN + #define INSN(NAME, op, width, mop, mew) \ void NAME(VectorRegister Vd, Register Rs1, VectorRegister Vs2, VectorMask vm = unmasked, Nf nf = g1) { \ patch_VLdSt(op, Vd, width, Rs1, Vs2->raw_encoding(), vm, mop, mew, nf); \ diff --git a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp index 198835d733f79..6a2c6c7d6c9bd 100644 --- a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp +++ b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp @@ -5103,6 +5103,225 @@ class StubGenerator: public StubCodeGenerator { return (address) start; } + /** + * vector registers: + * input VectorRegister's: intputV1-V3, for m2 they could be v2, v4, v6, for m1 they could be v1, v2, v3 + * index VectorRegister's: idxV1-V4, for m2 they could be v8, v10, v12, v14, for m1 they could be v4, v5, v6, v7 + * output VectorRegister's: outputV1-V4, for m2 they could be v16, v18, v20, v22, for m1 they could be v8, v9, v10, v11 + * + * NOTE: each field will occupy a vector register group + */ + void base64_vector_encode_round(Register src, Register dst, Register codec, + Register size, Register stepSrc, Register stepDst, + VectorRegister inputV1, VectorRegister inputV2, VectorRegister inputV3, + VectorRegister idxV1, VectorRegister idxV2, VectorRegister idxV3, VectorRegister idxV4, + VectorRegister outputV1, VectorRegister outputV2, VectorRegister outputV3, VectorRegister outputV4, + Assembler::LMUL lmul) { + // set vector register type/len + __ vsetvli(x0, size, Assembler::e8, lmul); + + // segmented load src into v registers: mem(src) => vr(3) + __ vlseg3e8_v(inputV1, src); + + // src = src + register_group_len_bytes * 3 + __ add(src, src, stepSrc); + + // encoding + // 1. compute index into lookup table: vr(3) => vr(4) + __ vsrl_vi(idxV1, inputV1, 2); + + __ vsrl_vi(idxV2, inputV2, 2); + __ vsll_vi(inputV1, inputV1, 6); + __ vor_vv(idxV2, idxV2, inputV1); + __ vsrl_vi(idxV2, idxV2, 2); + + __ vsrl_vi(idxV3, inputV3, 4); + __ vsll_vi(inputV2, inputV2, 4); + __ vor_vv(idxV3, inputV2, idxV3); + __ vsrl_vi(idxV3, idxV3, 2); + + __ vsll_vi(idxV4, inputV3, 2); + __ vsrl_vi(idxV4, idxV4, 2); + + // 2. indexed load: vr(4) => vr(4) + __ vluxei8_v(outputV1, codec, idxV1); + __ vluxei8_v(outputV2, codec, idxV2); + __ vluxei8_v(outputV3, codec, idxV3); + __ vluxei8_v(outputV4, codec, idxV4); + + // segmented store encoded data in v registers back to dst: vr(4) => mem(dst) + __ vsseg4e8_v(outputV1, dst); + + // dst = dst + register_group_len_bytes * 4 + __ add(dst, dst, stepDst); + } + + /** + * void j.u.Base64.Encoder.encodeBlock(byte[] src, int sp, int sl, byte[] dst, int dp, boolean isURL) + * + * Input arguments: + * c_rarg0 - src, source array + * c_rarg1 - sp, src start offset + * c_rarg2 - sl, src end offset + * c_rarg3 - dst, dest array + * c_rarg4 - dp, dst start offset + * c_rarg5 - isURL, Base64 or URL character set + */ + address generate_base64_encodeBlock() { + alignas(64) static const char toBase64[64] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' + }; + + alignas(64) static const char toBase64URL[64] = { + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', + 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '_' + }; + + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", "encodeBlock"); + address start = __ pc(); + __ enter(); + + Register src = c_rarg0; + Register soff = c_rarg1; + Register send = c_rarg2; + Register dst = c_rarg3; + Register doff = c_rarg4; + Register isURL = c_rarg5; + + Register codec = c_rarg6; + Register length = c_rarg7; // total length of src data in bytes + + Label ProcessData, Exit; + + // length should be multiple of 3 + __ sub(length, send, soff); + // real src/dst to process data + __ add(src, src, soff); + __ add(dst, dst, doff); + + // load the codec base address + __ la(codec, ExternalAddress((address) toBase64)); + __ beqz(isURL, ProcessData); + __ la(codec, ExternalAddress((address) toBase64URL)); + __ BIND(ProcessData); + + // vector version + if (UseRVV) { + Label ProcessM2, ProcessM1, ProcessScalar; + + Register size = soff; + Register stepSrcM1 = send; + Register stepSrcM2 = doff; + Register stepDst = isURL; + + __ mv(size, MaxVectorSize * 2); + __ mv(stepSrcM1, MaxVectorSize * 3); + __ slli(stepSrcM2, stepSrcM1, 1); + __ mv(stepDst, MaxVectorSize * 2 * 4); + + __ blt(length, stepSrcM2, ProcessM1); + + __ BIND(ProcessM2); + base64_vector_encode_round(src, dst, codec, + size, stepSrcM2, stepDst, + v2, v4, v6, // inputs + v8, v10, v12, v14, // indexes + v16, v18, v20, v22, // outputs + Assembler::m2); + + __ sub(length, length, stepSrcM2); + __ bge(length, stepSrcM2, ProcessM2); + + __ BIND(ProcessM1); + __ blt(length, stepSrcM1, ProcessScalar); + + __ srli(size, size, 1); + __ srli(stepDst, stepDst, 1); + base64_vector_encode_round(src, dst, codec, + size, stepSrcM1, stepDst, + v1, v2, v3, // inputs + v4, v5, v6, v7, // indexes + v8, v9, v10, v11, // outputs + Assembler::m1); + __ sub(length, length, stepSrcM1); + + __ BIND(ProcessScalar); + } + + // scalar version + { + Register byte1 = soff, byte0 = send, byte2 = doff; + Register combined24Bits = isURL; + + __ beqz(length, Exit); + + Label ScalarLoop; + __ BIND(ScalarLoop); + { + // plain: [byte0[7:0] : byte1[7:0] : byte2[7:0]] => + // encoded: [byte0[7:2] : byte0[1:0]+byte1[7:4] : byte1[3:0]+byte2[7:6] : byte2[5:0]] + + // load 3 bytes src data + __ lbu(byte0, Address(src, 0)); + __ lbu(byte1, Address(src, 1)); + __ lbu(byte2, Address(src, 2)); + __ addi(src, src, 3); + + // construct 24 bits from 3 bytes + __ slliw(byte0, byte0, 16); + __ slliw(byte1, byte1, 8); + __ orr(combined24Bits, byte0, byte1); + __ orr(combined24Bits, combined24Bits, byte2); + + // get codec index and encode(ie. load from codec by index) + __ slliw(byte0, combined24Bits, 8); + __ srliw(byte0, byte0, 26); + __ add(byte0, codec, byte0); + __ lbu(byte0, byte0); + + __ slliw(byte1, combined24Bits, 14); + __ srliw(byte1, byte1, 26); + __ add(byte1, codec, byte1); + __ lbu(byte1, byte1); + + __ slliw(byte2, combined24Bits, 20); + __ srliw(byte2, byte2, 26); + __ add(byte2, codec, byte2); + __ lbu(byte2, byte2); + + __ andi(combined24Bits, combined24Bits, 0x3f); + __ add(combined24Bits, codec, combined24Bits); + __ lbu(combined24Bits, combined24Bits); + + // store 4 bytes encoded data + __ sb(byte0, Address(dst, 0)); + __ sb(byte1, Address(dst, 1)); + __ sb(byte2, Address(dst, 2)); + __ sb(combined24Bits, Address(dst, 3)); + + __ sub(length, length, 3); + __ addi(dst, dst, 4); + // loop back + __ bnez(length, ScalarLoop); + } + } + + __ BIND(Exit); + + __ leave(); + __ ret(); + + return (address) start; + } + void adler32_process_bytes(Register buff, Register s1, Register s2, VectorRegister vtable, VectorRegister vzero, VectorRegister vbytes, VectorRegister vs1acc, VectorRegister vs2acc, Register temp0, Register temp1, Register temp2, Register temp3, @@ -5996,6 +6215,10 @@ static const int64_t right_3_bits = right_n_bits(3); StubRoutines::_sha1_implCompressMB = generate_sha1_implCompress(true, "sha1_implCompressMB"); } + if (UseBASE64Intrinsics) { + StubRoutines::_base64_encodeBlock = generate_base64_encodeBlock(); + } + if (UseAdler32Intrinsics) { StubRoutines::_updateBytesAdler32 = generate_updateBytesAdler32(); } diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.cpp b/src/hotspot/cpu/riscv/vm_version_riscv.cpp index ac2d6cde1a227..e9c6226f44639 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.cpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.cpp @@ -265,6 +265,11 @@ void VM_Version::c2_initialize() { // as there are extra checks inside it which could disable UseRVV // in some situations. + // Base64 + if (FLAG_IS_DEFAULT(UseBASE64Intrinsics)) { + FLAG_SET_DEFAULT(UseBASE64Intrinsics, true); + } + if (FLAG_IS_DEFAULT(UseVectorizedHashCodeIntrinsic)) { FLAG_SET_DEFAULT(UseVectorizedHashCodeIntrinsic, true); } From 140716078694a338e2c2f837841761262cee5542 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Walln=C3=B6fer?= Date: Fri, 9 Aug 2024 09:24:50 +0000 Subject: [PATCH 18/20] 8313931: Javadoc: links to type parameters actually generate links to classes Reviewed-by: jjg --- .../doclets/formats/html/ClassWriter.java | 50 +++++-- .../doclets/formats/html/HtmlIds.java | 16 +++ .../doclets/formats/html/HtmlLinkFactory.java | 13 +- .../formats/html/resources/script.js.template | 18 ++- .../formats/html/resources/stylesheet.css | 22 +++- .../formats/html/taglets/LinkTaglet.java | 24 +++- .../formats/html/taglets/ParamTaglet.java | 6 +- .../doclets/toolkit/util/CommentHelper.java | 6 + .../TestDeprecatedDocs.java | 8 +- .../TestDirectedInheritance.java | 6 +- .../doclet/testErasure/TestErasure.java | 8 +- .../TestGenericMethodLinkTaglet.java | 6 +- .../jdk/javadoc/doclet/testHref/TestHref.java | 5 +- .../doclet/testInterface/TestInterface.java | 36 ++--- .../TestLinkTagletTypeParam.java | 124 ++++++++++++++++++ .../TestMemberInheritance.java | 4 +- .../doclet/testModules/TestModules.java | 2 +- .../TestNewLanguageFeatures.java | 22 ++-- .../testParamTaglet/TestParamTaglet.java | 6 +- .../doclet/testProperty/TestProperty.java | 4 +- .../testRecordTypes/TestRecordTypes.java | 2 +- .../TestSerializedForm.java | 5 +- .../javadoc/doclet/testThrows/TestThrows.java | 4 +- .../testTypeParams/TestTypeParameters.java | 20 ++- .../testTypeParams/pkg/CtorTypeParam.java | 6 + .../doclet/testUnicode/TestUnicode.java | 4 +- 26 files changed, 336 insertions(+), 91 deletions(-) create mode 100644 test/langtools/jdk/javadoc/doclet/testLinkTaglet/TestLinkTagletTypeParam.java diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriter.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriter.java index a1fd27fefdd58..8218e5128be3b 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriter.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriter.java @@ -37,6 +37,7 @@ import javax.lang.model.element.Name; import javax.lang.model.element.PackageElement; import javax.lang.model.element.TypeElement; +import javax.lang.model.element.TypeParameterElement; import javax.lang.model.element.VariableElement; import javax.lang.model.type.TypeMirror; import javax.lang.model.util.SimpleElementVisitor8; @@ -155,7 +156,7 @@ protected void buildClassTree(Content classContent) { * @param target the content to which the documentation will be added */ protected void buildClassInfo(Content target) { - Content c = HtmlTree.DIV(HtmlStyles.horizontalScroll); + var c = new ContentBuilder(); buildParamInfo(c); buildSuperInterfacesInfo(c); buildImplementedInterfacesInfo(c); @@ -164,11 +165,13 @@ protected void buildClassInfo(Content target) { buildInterfaceUsageInfo(c); buildNestedClassInfo(c); buildFunctionalInterfaceInfo(c); - buildClassSignature(c); - buildDeprecationInfo(c); - buildClassDescription(c); - buildClassTagInfo(c); - + c.add(new HtmlTree(HtmlTag.HR)); + var div = HtmlTree.DIV(HtmlStyles.horizontalScroll); + buildClassSignature(div); + buildDeprecationInfo(div); + buildClassDescription(div); + buildClassTagInfo(div); + c.add(div); target.add(getClassInfo(c)); } @@ -432,12 +435,9 @@ private void setRecordDocumentation(TypeElement elem) { protected Content getHeader(String header) { HtmlTree body = getBody(getWindowTitle(utils.getSimpleName(typeElement))); var div = HtmlTree.DIV(HtmlStyles.header); - HtmlLinkInfo linkInfo = new HtmlLinkInfo(configuration, - HtmlLinkInfo.Kind.SHOW_TYPE_PARAMS_AND_BOUNDS, typeElement) - .linkToSelf(false); // Let's not link to ourselves in the header var heading = HtmlTree.HEADING_TITLE(Headings.PAGE_TITLE_HEADING, HtmlStyles.title, Text.of(header)); - heading.add(getTypeParameterLinks(linkInfo)); + heading.add(getTypeParameters()); div.add(heading); bodyContents.setHeader(getHeader(PageMode.CLASS, typeElement)) .addMainContent(MarkerComments.START_OF_CLASS_DATA) @@ -445,6 +445,35 @@ protected Content getHeader(String header) { return body; } + // Renders type parameters for the class heading, creating id attributes + // if @param block tags are missing in doc comment. + private Content getTypeParameters() { + var content = new ContentBuilder(); + var typeParams = typeElement.getTypeParameters(); + if (!typeParams.isEmpty()) { + // Generate id attributes if @param tags are missing for type parameters. + // Note that this does not handle the case where some but not all @param tags are missing. + var needsId = !utils.hasBlockTag(typeElement, DocTree.Kind.PARAM); + var linkInfo = new HtmlLinkInfo(configuration, + HtmlLinkInfo.Kind.SHOW_TYPE_PARAMS_AND_BOUNDS, typeElement) + .linkToSelf(false); // Let's not link to ourselves in the header + content.add("<"); + var first = true; + for (TypeParameterElement t : typeParams) { + if (!first) { + content.add(",").add(new HtmlTree(HtmlTag.WBR)); + } + var typeParamLink = getLink(linkInfo.forType(t.asType())); + content.add(needsId + ? HtmlTree.SPAN_ID(htmlIds.forTypeParam(t.getSimpleName().toString(), typeElement), typeParamLink) + : typeParamLink); + first = false; + } + content.add(">"); + } + return content; + } + protected Content getClassContentHeader() { return getContentHeader(); } @@ -473,7 +502,6 @@ public TypeElement getCurrentPageElement() { } protected void addClassSignature(Content classInfo) { - classInfo.add(new HtmlTree(HtmlTag.HR)); classInfo.add(new Signatures.TypeSignature(typeElement, this) .toContent()); } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlIds.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlIds.java index 1b9896fafa006..8b48c7a6f2262 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlIds.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlIds.java @@ -462,6 +462,22 @@ public static HtmlId forText(String text, Map counts) { return HtmlId.of(count == 0 ? base : base + "-" + count); } + /** + * Returns an id for text documenting a type parameter of a class or method. + * + * @param paramName the name of the type parameter + * @param owner the enclosing element + * + * @return the id + */ + public HtmlId forTypeParam(String paramName, Element owner) { + if (utils.isExecutableElement(owner)) { + return HtmlId.of(forMember((ExecutableElement) owner).getFirst().name() + + "-type-param-" + paramName); + } + return HtmlId.of("type-param-" + paramName); + } + /** * Returns an id for one of the kinds of section in the pages for item group summaries. * diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlLinkFactory.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlLinkFactory.java index 22af1e4a0244c..8e0c010dd1ae4 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlLinkFactory.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlLinkFactory.java @@ -162,9 +162,11 @@ public Content visitTypeVariable(TypeVariable type, HtmlLinkInfo linkInfo) { Element owner = typevariable.asElement().getEnclosingElement(); if (linkInfo.linkTypeParameters() && utils.isTypeElement(owner)) { linkInfo.setTypeElement((TypeElement) owner); - Content label = newContent(); - label.add(utils.getTypeName(type, false)); - linkInfo.label(label).skipPreview(true); + if (linkInfo.getLabel() == null || linkInfo.getLabel().isEmpty()) { + Content label = newContent(); + label.add(utils.getTypeName(type, false)); + linkInfo.label(label).skipPreview(true); + } link.add(getClassLink(linkInfo)); } else { // No need to link method type parameters. @@ -242,6 +244,11 @@ protected Content getClassLink(HtmlLinkInfo linkInfo) { boolean isTypeLink = linkInfo.getType() != null && utils.isTypeVariable(utils.getComponentType(linkInfo.getType())); title = getClassToolTip(typeElement, isTypeLink); + if (isTypeLink) { + linkInfo.fragment(m_writer.configuration.htmlIds.forTypeParam( + utils.getTypeName(utils.getComponentType(linkInfo.getType()), false), + typeElement).name()); + } } Content label = linkInfo.getClassLinkLabel(configuration); if (linkInfo.getContext() == HtmlLinkInfo.Kind.SHOW_TYPE_PARAMS_IN_LABEL) { 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 ef09e6df90fd7..71ef847670822 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 @@ -232,6 +232,20 @@ document.addEventListener("readystatechange", (e) => { }); document.addEventListener("DOMContentLoaded", function(e) { setTopMargin(); + // Reset animation for type parameter target highlight + document.querySelectorAll("a").forEach((link) => { + link.addEventListener("click", (e) => { + const href = e.currentTarget.getAttribute("href"); + if (href && href.startsWith("#") && href.indexOf("type-param-") > -1) { + const target = document.getElementById(decodeURI(href.substring(1))); + if (target) { + target.style.animation = "none"; + void target.offsetHeight; + target.style.removeProperty("animation"); + } + } + }) + }); // Make sure current element is visible in breadcrumb navigation on small displays const subnav = document.querySelector("ol.sub-nav-list"); if (subnav && subnav.lastElementChild) { @@ -286,7 +300,7 @@ document.addEventListener("DOMContentLoaded", function(e) { }); var expanded = false; var windowWidth; - function collapse() { + function collapse(e) { if (expanded) { mainnav.removeAttribute("style"); if (toc) { @@ -336,7 +350,7 @@ document.addEventListener("DOMContentLoaded", function(e) { document.querySelectorAll("h1, h2, h3, h4, h5, h6") .forEach((hdr, idx) => { // Create anchor links for headers with an associated id attribute - var id = hdr.getAttribute("id") || hdr.parentElement.getAttribute("id") + var id = hdr.parentElement.getAttribute("id") || hdr.getAttribute("id") || (hdr.querySelector("a") && hdr.querySelector("a").getAttribute("id")); if (id) { var template = document.createElement('template'); 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 4e37588f6cda5..1130f14dc35b4 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 @@ -63,7 +63,7 @@ --search-input-text-color: #000000; --search-input-placeholder-color: #909090; /* Highlight color for active search tag target */ - --search-tag-highlight-color: #ffff00; + --search-tag-highlight-color: #ffff66; /* Adjustments for icon and active background colors of copy-to-clipboard buttons */ --copy-icon-brightness: 100%; --copy-button-background-color-active: rgba(168, 168, 176, 0.3); @@ -307,7 +307,7 @@ ol.sub-nav-list a.current-selection { */ .title { color:var(--title-color); - margin:10px 0; + margin:10px 0 12px 0; } .sub-title { margin:5px 0 0 0; @@ -988,6 +988,22 @@ input::placeholder { .search-tag-result:target { background-color:var(--search-tag-highlight-color); } +dd > span:target, +h1 > span:target { + animation: 2.4s ease-out highlight; +} +section.class-description dd > span:target, +section.class-description h1 > span:target { + scroll-margin-top: 20em; +} +@keyframes highlight { + from { + background-color: var(--search-tag-highlight-color); + } + 60% { + background-color: var(--search-tag-highlight-color); + } +} details.page-search-details { display: inline-block; } @@ -1040,7 +1056,7 @@ span#page-search-link { z-index: 5; } .inherited-list { - margin: 10px 0 10px 0; + margin: 10px 0; } .horizontal-scroll { overflow: auto hidden; diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/LinkTaglet.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/LinkTaglet.java index e16acd0315ad7..b16a1490b6303 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/LinkTaglet.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/LinkTaglet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -176,7 +176,7 @@ Content linkSeeReferenceOutput(Element holder, return htmlWriter.getPackageLink(refPackage, labelContent, refFragment); } else { // @see is not referencing an included class, module or package. Check for cross-links. - String refModuleName = ch.getReferencedModuleName(refSignature); + String refModuleName = ch.getReferencedModuleName(refSignature); DocLink elementCrossLink = (refPackage != null) ? htmlWriter.getCrossPackageLink(refPackage) : (config.extern.isModule(refModuleName)) ? htmlWriter.getCrossModuleLink(utils.elementUtils.getModuleElement(refModuleName)) @@ -190,12 +190,28 @@ Content linkSeeReferenceOutput(Element holder, if (!config.isDocLintReferenceGroupEnabled()) { reportWarning.accept( "doclet.link.see.reference_not_found", - new Object[] { refSignature}); + new Object[] {refSignature}); } return htmlWriter.invalidTagOutput(resources.getText("doclet.link.see.reference_invalid"), - Optional.of(labelContent.isEmpty() ? text: labelContent)); + Optional.of(labelContent.isEmpty() ? text : labelContent)); } } + } else if (utils.isTypeParameterElement(ref)) { + // This is a type parameter of a generic class, method or constructor + if (labelContent.isEmpty()) { + labelContent = plainOrCode(isPlain, Text.of(utils.getSimpleName(ref))); + } + if (refMem == null) { + return htmlWriter.getLink( + new HtmlLinkInfo(config, HtmlLinkInfo.Kind.LINK_TYPE_PARAMS, ref.asType()) + .label(labelContent)); + } else { + // HtmlLinkFactory does not render type parameters of generic methods as links, so instead of + // teaching it how to do it (making the code even more complex) just create the link directly. + return htmlWriter.getLink(new HtmlLinkInfo(config, HtmlLinkInfo.Kind.PLAIN, refClass) + .fragment(config.htmlIds.forTypeParam(ref.getSimpleName().toString(), refMem).name()) + .label((labelContent))); + } } else if (refFragment == null) { // Must be a class reference since refClass is not null and refFragment is null. if (labelContent.isEmpty() && refTree != null) { diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/ParamTaglet.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/ParamTaglet.java index ed46e6c5c864f..8a3c47bbfd4b6 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/ParamTaglet.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/taglets/ParamTaglet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -278,7 +278,9 @@ private Content paramTagOutput(Element element, ParamTree paramTag, String param body.add(" - "); List description = ch.getDescription(paramTag); body.add(htmlWriter.commentTagsToContent(element, description, context.within(paramTag))); - return HtmlTree.DD(body); + return HtmlTree.DD(paramTag.isTypeParameter() + ? HtmlTree.SPAN_ID(config.htmlIds.forTypeParam(paramName, element), body) + : body); } private record Documentation(ParamTree paramTree, ExecutableElement method) { } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/CommentHelper.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/CommentHelper.java index d7a0bd2d0a070..30aa86aea7196 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/CommentHelper.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/CommentHelper.java @@ -188,6 +188,12 @@ public Element getReferencedMember(Element e) { Utils utils = configuration.utils; if (e == null) { return null; + } else if (utils.isTypeParameterElement(e)) { + // Return the enclosing member for type parameters of generic methods or constructors. + Element encl = e.getEnclosingElement(); + if (utils.isExecutableElement(encl)) { + return encl; + } } return (utils.isExecutableElement(e) || utils.isVariableElement(e)) ? e : null; } diff --git a/test/langtools/jdk/javadoc/doclet/testDeprecatedDocs/TestDeprecatedDocs.java b/test/langtools/jdk/javadoc/doclet/testDeprecatedDocs/TestDeprecatedDocs.java index 2bd9da5957837..165fadc8e051f 100644 --- a/test/langtools/jdk/javadoc/doclet/testDeprecatedDocs/TestDeprecatedDocs.java +++ b/test/langtools/jdk/javadoc/doclet/testDeprecatedDocs/TestDeprecatedDocs.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -102,7 +102,6 @@ public void test() { checkOutput("pkg/TestAnnotationType.html", true, """ -
@Deprecated(forRemoval=true) @Documented public @interface
@Deprecated(forRemoval=true) public class TestClass extends java.lang.Object
@@ -212,7 +210,6 @@ public void test() { checkOutput("pkg/TestEnum.html", true, """ -
@Deprecated(forRemoval=true) public enum TestEnum extends java.lang.Enum<
@Deprecated(forRemoval=true) public class TestError extends java.lang.Error
@@ -244,7 +240,6 @@ public void test() { checkOutput("pkg/TestException.html", true, """ -
@Deprecated(forRemoval=true) public class TestException extends java.lang.Exception
@@ -255,7 +250,6 @@ public void test() { checkOutput("pkg/TestInterface.html", true, """ -
@Deprecated(forRemoval=true) public class TestInterface extends java.lang.Object
diff --git a/test/langtools/jdk/javadoc/doclet/testDirectedInheritance/TestDirectedInheritance.java b/test/langtools/jdk/javadoc/doclet/testDirectedInheritance/TestDirectedInheritance.java index 89eb68db1dfdc..0f2b398e626bc 100644 --- a/test/langtools/jdk/javadoc/doclet/testDirectedInheritance/TestDirectedInheritance.java +++ b/test/langtools/jdk/javadoc/doclet/testDirectedInheritance/TestDirectedInheritance.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -154,8 +154,8 @@ public interface E1 extends I1, I2 {
I2: main description
""", """
Type Parameters:
-
E - I2: first type parameter
-
F - I2: second type parameter
+
E - I2: first type parameter
+
F - I2: second type parameter
Parameters:
eObj - I2: parameter
Returns:
diff --git a/test/langtools/jdk/javadoc/doclet/testErasure/TestErasure.java b/test/langtools/jdk/javadoc/doclet/testErasure/TestErasure.java index f80074c50e250..ee2ec08b884e6 100644 --- a/test/langtools/jdk/javadoc/doclet/testErasure/TestErasure.java +++ b/test/langtools/jdk/javadoc/doclet/testErasure/TestErasure.java @@ -199,7 +199,7 @@ class X { }
 
\ Foo\ - (T arg)
+ (T arg)
 
 <T extends X>
\ @@ -227,10 +227,10 @@ class X { } // methods checkOutput("Foo.html", true, """
abstract T
+ method-summary-table-tab3">abstract T
m\ - (T arg)
+ (T arg)
 
Test Feature
"""); } -} \ No newline at end of file +} diff --git a/test/langtools/jdk/javadoc/doclet/testGenericMethodLinkTaglet/TestGenericMethodLinkTaglet.java b/test/langtools/jdk/javadoc/doclet/testGenericMethodLinkTaglet/TestGenericMethodLinkTaglet.java index a9a4be1b262b9..db23064e9ca8d 100644 --- a/test/langtools/jdk/javadoc/doclet/testGenericMethodLinkTaglet/TestGenericMethodLinkTaglet.java +++ b/test/langtools/jdk/javadoc/doclet/testGenericMethodLinkTaglet/TestGenericMethodLinkTaglet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8188248 + * @bug 8188248 8313931 * @summary NullPointerException on generic methods * @library /tools/lib ../../lib * @modules jdk.javadoc/jdk.javadoc.internal.tool @@ -67,7 +67,7 @@ public void test(Path base) throws Exception { checkOutput("pkg/A.html", true, """ - A"""); + param T"""); } void createTestClass(Path srcDir) throws Exception { diff --git a/test/langtools/jdk/javadoc/doclet/testHref/TestHref.java b/test/langtools/jdk/javadoc/doclet/testHref/TestHref.java index f21ad223fb459..b9dff5ff2a897 100644 --- a/test/langtools/jdk/javadoc/doclet/testHref/TestHref.java +++ b/test/langtools/jdk/javadoc/doclet/testHref/TestHref.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -75,7 +75,8 @@ public void test() { checkOutput("pkg/C4.html", true, //Header does not link to the page itself. - "Class C4<E extends C4<E>>", + """ + Class C4<E extends C4<E>>""", //Signature does not link to the page itself. """ public abstract class method in interface&\ nbsp;Interface<CE>""", + href="#type-param-CE" title="type parameter in Child">CE>""", //Make sure "Overrides" has substituted type parameters. """
Overrides:
method in class Parent<Parent<CE>
"""); checkOutput("pkg/Parent.html", true, @@ -190,7 +190,7 @@ public void test1() {
Overrides:
method1 in class&\ nbsp;GrandParent<<\ - a href="Child.html" title="type parameter in Child">CE>"""); + a href="#type-param-CE" title="type parameter in Child">CE>"""); } @Test @@ -209,17 +209,17 @@ public void test2() { erface in pkg2">Spliterator Spliterator.\ OfDouble, Spliter\ - ator.OfInt<Integer>, Spliterator.OfPrimitive<T,T_C\ - ONS,T,T_C\ + ONS,T_SPLITR extends Spliterator.OfPrimitive<T,<\ - a href="Spliterator.OfPrimitive.html" title="type parameter in Spliterator.OfPri\ - mitive">T_CONS,T,<\ + a href="Spliterator.OfPrimitive.html#type-param-T_CONS" title="type parameter in Spliterator.OfPri\ + mitive">T_CONS,T_SPLITR>>"""); checkOutput("pkg2/Spliterator.html", true, """ @@ -236,21 +236,21 @@ public void test2() {
static interface 
Spliterator.OfInt<Integer&\ + Spliterator.OfInt.html#type-param-Integer" title="type parameter in Spliterator.OfInt">Integer&\ gt;
 
static interface 
Spliterator.OfPrimitive\ - <T,T,T_CONS,T_SPLITR extends <\ + e.html#type-param-T_SPLITR" title="type parameter in Spliterator.OfPrimitive">T_SPLITR extends <\ a href="Spliterator.OfPrimitive.html" title="interface in pkg2">Spliterator.OfPr\ - imitive<T,<T,T_CONS,T_SPLITRT_SPLITR>>
 
"""); diff --git a/test/langtools/jdk/javadoc/doclet/testLinkTaglet/TestLinkTagletTypeParam.java b/test/langtools/jdk/javadoc/doclet/testLinkTaglet/TestLinkTagletTypeParam.java new file mode 100644 index 0000000000000..5cb1f687d452f --- /dev/null +++ b/test/langtools/jdk/javadoc/doclet/testLinkTaglet/TestLinkTagletTypeParam.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 8313931 + * @summary Javadoc: links to type parameters actually generate links to classes + * @library /tools/lib ../../lib + * @modules jdk.javadoc/jdk.javadoc.internal.tool + * @build toolbox.ToolBox javadoc.tester.* + * @run main TestLinkTagletTypeParam + */ + +import javadoc.tester.JavadocTester; +import toolbox.ToolBox; + +import java.io.IOException; +import java.nio.file.Path; + +public class TestLinkTagletTypeParam extends JavadocTester { + + public static void main(String... args) throws Exception { + var tester = new TestLinkTagletTypeParam(); + tester.runTests(); + } + + ToolBox tb = new ToolBox(); + + @JavadocTester.Test + public void testClassTypeParameterLink(Path base) throws IOException { + Path src = base.resolve("src"); + + tb.writeJavaFiles(src, + """ + /** + * Link to {@link F}. + * + * @param the first type param + * @param an Appendable + * + * @see APND the second type parameter + */ + public class Test { + private Test() {} + } + """); + + javadoc("-Xdoclint:none", + "-d", base.resolve("api").toString(), + "-sourcepath", src.toString(), + src.resolve("Test.java").toString()); + checkExit(JavadocTester.Exit.OK); + + checkOrder("Test.html", + """ +
Type Parameters:
+
F - the first type param
+
APND - an Appendable
""", + """ + Link to
F.""", + """ +
See Also:
+
+ """); + } + + @JavadocTester.Test + public void testMethodTypeParameterLink(Path base) throws IOException { + Path src = base.resolve("src"); + + tb.writeJavaFiles(src, + """ + /** + * Class comment. + */ + public class Test { + /** + * Link to {@link T} and {@linkplain T link with label}. + * + * @param the T + * @param appendable the appendable + */ + public T append(final T appendable) { + return appendable; + } + } + """); + + javadoc("-Xdoclint:reference", + "-d", base.resolve("api").toString(), + "-sourcepath", src.toString(), + src.resolve("Test.java").toString()); + + checkOutput(JavadocTester.Output.OUT, true, + ""); + + checkOutput("Test.html", true, + """ + Link to T and link with label."""); + } +} diff --git a/test/langtools/jdk/javadoc/doclet/testMemberInheritance/TestMemberInheritance.java b/test/langtools/jdk/javadoc/doclet/testMemberInheritance/TestMemberInheritance.java index 705cae327e3a3..559f7b08d3877 100644 --- a/test/langtools/jdk/javadoc/doclet/testMemberInheritance/TestMemberInheritance.java +++ b/test/langtools/jdk/javadoc/doclet/testMemberInheritance/TestMemberInheritance.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -120,8 +120,8 @@ interface in pkg">BaseInterface
checkOutput("pkg2/DocumentedNonGenericChild.html", true, """
-

+
public abstract class DocumentedNonGenericChild extends java.lang.Object
diff --git a/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java b/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java index 79bad12f95db2..4d3628544f81e 100644 --- a/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java +++ b/test/langtools/jdk/javadoc/doclet/testModules/TestModules.java @@ -1360,8 +1360,8 @@ void checkLinkSource(boolean includePrivate) { checkOutput("moduleA/testpkgmdlA/TestClassInModuleA.html", true, """
-

+
public class TestClassInModuleA diff --git a/test/langtools/jdk/javadoc/doclet/testNewLanguageFeatures/TestNewLanguageFeatures.java b/test/langtools/jdk/javadoc/doclet/testNewLanguageFeatures/TestNewLanguageFeatures.java index a54fbbcff75f0..eafad8c3245f2 100644 --- a/test/langtools/jdk/javadoc/doclet/testNewLanguageFeatures/TestNewLanguageFeatures.java +++ b/test/langtools/jdk/javadoc/doclet/testNewLanguageFeatures/TestNewLanguageFeatures.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -117,7 +117,7 @@ void checkTypeParameters() { // Check class type parameters section. """
Type Parameters:
-
E - the type parameter for this class.""", +
E - the type parameter for this class.
""", // Type parameters in @see/@link """
@@ -130,12 +130,14 @@ void checkTypeParameters() {
""", // Method that uses class type parameter. """ - (E param)""", + (E param)""", // Method type parameter section. """
Type Parameters:
-
T - This is the first type parameter.
-
V - This is the second type parameter.""", +
T - Th\ + is is the first type parameter.
+
V - Th\ + is is the second type parameter.
""", // Signature of method with type parameters """
public E[]
methodThatReturnsTypeParameterA(E[] \ + ref="#type-param-E" title="type parameter in TypeParameters">E[] \ e)""", """
public E[] methodThatReturnsTypePa\ - rameterA((E[] e)
""", """ @@ -176,7 +178,7 @@ void checkTypeParameters() { """
<X extends java.lang.Throwable>
E
\ + href="#type-param-E" title="type parameter in TypeParameters">E
\
Type Parameters: -
T2 - type 2
+
T2 - type 2
Parameters:
t1 - param 1
t3 - param 3
@@ -92,7 +92,7 @@ public void test() { checkOutput("pkg/C.Nested.html", true, """
Type Parameters:
-
T1 - type 1
+
T1 - type 1
"""); } } diff --git a/test/langtools/jdk/javadoc/doclet/testProperty/TestProperty.java b/test/langtools/jdk/javadoc/doclet/testProperty/TestProperty.java index 7ce046c07575c..94ad1a8040f6a 100644 --- a/test/langtools/jdk/javadoc/doclet/testProperty/TestProperty.java +++ b/test/langtools/jdk/javadoc/doclet/testProperty/TestProperty.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -110,7 +110,7 @@ class in pkg">ObjectProperty
<public final <\ span class="return-type">Obje\ - ctProperty<java.util.List<T>> listProperty<\ /div>
This is an Object property where the Object is a single List<T>.
diff --git a/test/langtools/jdk/javadoc/doclet/testRecordTypes/TestRecordTypes.java b/test/langtools/jdk/javadoc/doclet/testRecordTypes/TestRecordTypes.java index f9aa3cfd6fa49..3b6a8a4fc72e4 100644 --- a/test/langtools/jdk/javadoc/doclet/testRecordTypes/TestRecordTypes.java +++ b/test/langtools/jdk/javadoc/doclet/testRecordTypes/TestRecordTypes.java @@ -175,7 +175,7 @@ public record R(int r1) { }"""); """
Type Parameters:
-
T - This is a type parameter.
+
T - This is a type parameter.
Record Components:
r1 - This is a component.
""", diff --git a/test/langtools/jdk/javadoc/doclet/testSerializedForm/TestSerializedForm.java b/test/langtools/jdk/javadoc/doclet/testSerializedForm/TestSerializedForm.java index 9bf2ac362c611..af3e36aa7d897 100644 --- a/test/langtools/jdk/javadoc/doclet/testSerializedForm/TestSerializedForm.java +++ b/test/langtools/jdk/javadoc/doclet/testSerializedForm/TestSerializedForm.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 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 @@ -219,6 +219,7 @@ public void test2() { """ Fields[] singleArray""", """ - java.lang.Class<E> someClass"""); + java.lang.Class<E> someClass"""); } } diff --git a/test/langtools/jdk/javadoc/doclet/testThrows/TestThrows.java b/test/langtools/jdk/javadoc/doclet/testThrows/TestThrows.java index ca4592ea5f84c..e4c578578998f 100644 --- a/test/langtools/jdk/javadoc/doclet/testThrows/TestThrows.java +++ b/test/langtools/jdk/javadoc/doclet/testThrows/TestThrows.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -83,7 +83,7 @@ public interface C { """
Type Parameters:
-
T - the throwable
+
T - the throwable
Throws:
T - if a specific error occurs
java.lang.Exception - if an exception occurs
diff --git a/test/langtools/jdk/javadoc/doclet/testTypeParams/TestTypeParameters.java b/test/langtools/jdk/javadoc/doclet/testTypeParams/TestTypeParameters.java index 0d95ee38cdc94..dad610acb302e 100644 --- a/test/langtools/jdk/javadoc/doclet/testTypeParams/TestTypeParameters.java +++ b/test/langtools/jdk/javadoc/doclet/testTypeParams/TestTypeParameters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 4927167 4974929 6381729 7010344 8025633 8081854 8182765 8187288 8261976 + * @bug 4927167 4974929 6381729 7010344 8025633 8081854 8182765 8187288 8261976 8313931 * @summary When the type parameters are more than 10 characters in length, * make sure there is a line break between type params and return type * in member summary. Also, test for type parameter links in package-summary and @@ -110,10 +110,22 @@ public void test3() {
 <T extends java.lang.Runnable>
-
 
""", +
+
Generic constructor.
""", """
public\  <T extends java.lang.Runnable>\ -  CtorTypeParam()
"""); +  CtorTypeParam()
""", + """ + T""", + """ +
Type Parameters:
+
T - the type parameter
""", + """ +
See Also:
+
+ """); } } diff --git a/test/langtools/jdk/javadoc/doclet/testTypeParams/pkg/CtorTypeParam.java b/test/langtools/jdk/javadoc/doclet/testTypeParams/pkg/CtorTypeParam.java index a7f2309475d28..690471861dbd9 100644 --- a/test/langtools/jdk/javadoc/doclet/testTypeParams/pkg/CtorTypeParam.java +++ b/test/langtools/jdk/javadoc/doclet/testTypeParams/pkg/CtorTypeParam.java @@ -24,6 +24,12 @@ package pkg; public class CtorTypeParam { + /** + * Generic constructor. {@link T} + * + * @param the type parameter + * @see T link to type parameter + */ public CtorTypeParam() { } } diff --git a/test/langtools/jdk/javadoc/doclet/testUnicode/TestUnicode.java b/test/langtools/jdk/javadoc/doclet/testUnicode/TestUnicode.java index 76008260343ca..cf30488ec7bc2 100644 --- a/test/langtools/jdk/javadoc/doclet/testUnicode/TestUnicode.java +++ b/test/langtools/jdk/javadoc/doclet/testUnicode/TestUnicode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -101,7 +101,7 @@ public class Code<##> { """
Type Parameters:
-
## - the ##
+
## - the ##
""".replaceAll("##", chineseElephant), """ From 2b5aec2aad3883d4d407ec3a572f78755d60190d Mon Sep 17 00:00:00 2001 From: Alexander Zvegintsev Date: Fri, 9 Aug 2024 11:28:59 +0000 Subject: [PATCH 19/20] 8338109: java/awt/Mouse/EnterExitEvents/ResizingFrameTest.java duplicate in ProblemList Reviewed-by: aivanov --- test/jdk/ProblemList.txt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 293d9d108d32c..6cde711138310 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -375,7 +375,7 @@ java/awt/Modal/MultipleDialogs/MultipleDialogs3Test.java 8198665 macosx-all java/awt/Modal/MultipleDialogs/MultipleDialogs4Test.java 8198665 macosx-all java/awt/Modal/MultipleDialogs/MultipleDialogs5Test.java 8198665 macosx-all java/awt/Mouse/EnterExitEvents/DragWindowOutOfFrameTest.java 8177326 macosx-all -java/awt/Mouse/EnterExitEvents/ResizingFrameTest.java 8005021 macosx-all +java/awt/Mouse/EnterExitEvents/ResizingFrameTest.java 8005021,8332158 macosx-all,linux-x64 java/awt/Mouse/EnterExitEvents/FullscreenEnterEventTest.java 8051455 macosx-all java/awt/Mouse/MouseModifiersUnitTest/MouseModifiersUnitTest_Standard.java 7124407,8302787 macosx-all,windows-all java/awt/Mouse/RemovedComponentMouseListener/RemovedComponentMouseListener.java 8157170 macosx-all @@ -475,7 +475,6 @@ java/awt/Choice/SelectNewItemTest/SelectNewItemTest.java 8324782 macosx-all # Wayland related -java/awt/Mouse/EnterExitEvents/ResizingFrameTest.java 8332158 linux-x64 java/awt/FullScreen/FullscreenWindowProps/FullscreenWindowProps.java 8280991 linux-x64 java/awt/FullScreen/SetFullScreenTest.java 8332155 linux-x64 From 069e0ea69f43960164d3e077d2c7b950cde77927 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Fri, 9 Aug 2024 12:00:15 +0000 Subject: [PATCH 20/20] 8338064: Give better error for ConcurrentHashTable corruption Reviewed-by: dholmes, shade --- .../share/utilities/concurrentHashTable.hpp | 5 ++ .../utilities/concurrentHashTable.inline.hpp | 6 +- .../StringTableCorruptionTest.java | 59 +++++++++++++++++++ 3 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 test/hotspot/jtreg/runtime/stringtable/StringTableCorruptionTest.java diff --git a/src/hotspot/share/utilities/concurrentHashTable.hpp b/src/hotspot/share/utilities/concurrentHashTable.hpp index 991ea9fe3c609..4e506d5fe84f1 100644 --- a/src/hotspot/share/utilities/concurrentHashTable.hpp +++ b/src/hotspot/share/utilities/concurrentHashTable.hpp @@ -65,6 +65,7 @@ class ConcurrentHashTable : public CHeapObj { // the InternalTable or user-defined memory. class Node { private: + DEBUG_ONLY(size_t _saved_hash); Node * volatile _next; VALUE _value; public: @@ -77,6 +78,10 @@ class ConcurrentHashTable : public CHeapObj { Node* next() const; void set_next(Node* node) { _next = node; } Node* const volatile * next_ptr() { return &_next; } +#ifdef ASSERT + size_t saved_hash() const { return _saved_hash; } + void set_saved_hash(size_t hash) { _saved_hash = hash; } +#endif VALUE* value() { return &_value; } diff --git a/src/hotspot/share/utilities/concurrentHashTable.inline.hpp b/src/hotspot/share/utilities/concurrentHashTable.inline.hpp index 78c7e148bbb3c..f035aeae44847 100644 --- a/src/hotspot/share/utilities/concurrentHashTable.inline.hpp +++ b/src/hotspot/share/utilities/concurrentHashTable.inline.hpp @@ -679,7 +679,9 @@ inline bool ConcurrentHashTable:: // Keep in odd list odd = aux->next_ptr(); } else { - fatal("aux_index does not match even or odd indices"); + const char* msg = "Cannot resize table: Node hash code has changed possibly due to corruption of the contents."; + DEBUG_ONLY(fatal("%s Node hash code changed from " SIZE_FORMAT " to " SIZE_FORMAT, msg, aux->saved_hash(), aux_hash);) + NOT_DEBUG(fatal("%s", msg);) } } aux = aux_next; @@ -892,6 +894,7 @@ inline bool ConcurrentHashTable:: size_t i = 0; uintx hash = lookup_f.get_hash(); Node* new_node = Node::create_node(_context, value, nullptr); + DEBUG_ONLY(new_node->set_saved_hash(hash);) while (true) { { @@ -1117,6 +1120,7 @@ inline bool ConcurrentHashTable:: Bucket* bucket = get_bucket_in(table, hash); assert(!bucket->have_redirect() && !bucket->is_locked(), "bad"); Node* new_node = Node::create_node(_context, value, bucket->first()); + DEBUG_ONLY(new_node->set_saved_hash(hash);) if (!bucket->cas_first(new_node, bucket->first())) { assert(false, "bad"); } diff --git a/test/hotspot/jtreg/runtime/stringtable/StringTableCorruptionTest.java b/test/hotspot/jtreg/runtime/stringtable/StringTableCorruptionTest.java new file mode 100644 index 0000000000000..e4d6a2e5d0f95 --- /dev/null +++ b/test/hotspot/jtreg/runtime/stringtable/StringTableCorruptionTest.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 8333356 + * @summary Verify new error message for corrupting string table contents. + * @requires vm.flagless + * @modules java.base/java.lang:open + * @library /test/lib + * @modules java.base/jdk.internal.misc + * @run driver StringTableCorruptionTest test + */ + +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class StringTableCorruptionTest { + public static void main(String[] args) throws Exception { + if (args.length > 0) { + ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder("--add-opens", "java.base/java.lang=ALL-UNNAMED", + "-XX:-CreateCoredumpOnCrash", "StringTableCorruptionTest"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("Node hash code has changed possibly due to corruption of the contents."); + output.shouldNotHaveExitValue(0); + return; + } + + Field f = String.class.getDeclaredField("value"); + f.setAccessible(true); + f.set("s1".intern(), f.get("s2")); + for (int i = 0; i < 4_000_000; i++) { + ("s_" + i).intern(); + } + } +}