From ed9f3243f04718a50bbdc589437872f7215c0e08 Mon Sep 17 00:00:00 2001 From: Tobias Hartmann Date: Fri, 5 Jan 2024 15:40:32 +0000 Subject: [PATCH 1/7] 8322985: [BACKOUT] 8318562: Computational test more than 2x slower when AVX instructions are used Reviewed-by: chagedorn, shade --- src/hotspot/cpu/x86/macroAssembler_x86.cpp | 86 ----------- src/hotspot/cpu/x86/macroAssembler_x86.hpp | 17 --- src/hotspot/cpu/x86/x86_64.ad | 4 +- .../bench/vm/compiler/x86/ComputePI.java | 142 ------------------ 4 files changed, 2 insertions(+), 247 deletions(-) delete mode 100644 test/micro/org/openjdk/bench/vm/compiler/x86/ComputePI.java diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index aec1f3c9105a9..882966564859e 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -1871,92 +1871,6 @@ void MacroAssembler::cmpoop(Register src1, jobject src2, Register rscratch) { } #endif -void MacroAssembler::cvtss2sd(XMMRegister dst, XMMRegister src) { - if ((UseAVX > 0) && (dst != src)) { - xorpd(dst, dst); - } - Assembler::cvtss2sd(dst, src); -} - -void MacroAssembler::cvtss2sd(XMMRegister dst, Address src) { - if (UseAVX > 0) { - xorpd(dst, dst); - } - Assembler::cvtss2sd(dst, src); -} - -void MacroAssembler::cvtsd2ss(XMMRegister dst, XMMRegister src) { - if ((UseAVX > 0) && (dst != src)) { - xorps(dst, dst); - } - Assembler::cvtsd2ss(dst, src); -} - -void MacroAssembler::cvtsd2ss(XMMRegister dst, Address src) { - if (UseAVX > 0) { - xorps(dst, dst); - } - Assembler::cvtsd2ss(dst, src); -} - -void MacroAssembler::cvtsi2sdl(XMMRegister dst, Register src) { - if (UseAVX > 0) { - xorpd(dst, dst); - } - Assembler::cvtsi2sdl(dst, src); -} - -void MacroAssembler::cvtsi2sdl(XMMRegister dst, Address src) { - if (UseAVX > 0) { - xorpd(dst, dst); - } - Assembler::cvtsi2sdl(dst, src); -} - -void MacroAssembler::cvtsi2ssl(XMMRegister dst, Register src) { - if (UseAVX > 0) { - xorps(dst, dst); - } - Assembler::cvtsi2ssl(dst, src); -} - -void MacroAssembler::cvtsi2ssl(XMMRegister dst, Address src) { - if (UseAVX > 0) { - xorps(dst, dst); - } - Assembler::cvtsi2ssl(dst, src); -} - -#ifdef _LP64 -void MacroAssembler::cvtsi2sdq(XMMRegister dst, Register src) { - if (UseAVX > 0) { - xorpd(dst, dst); - } - Assembler::cvtsi2sdq(dst, src); -} - -void MacroAssembler::cvtsi2sdq(XMMRegister dst, Address src) { - if (UseAVX > 0) { - xorpd(dst, dst); - } - Assembler::cvtsi2sdq(dst, src); -} - -void MacroAssembler::cvtsi2ssq(XMMRegister dst, Register src) { - if (UseAVX > 0) { - xorps(dst, dst); - } - Assembler::cvtsi2ssq(dst, src); -} - -void MacroAssembler::cvtsi2ssq(XMMRegister dst, Address src) { - if (UseAVX > 0) { - xorps(dst, dst); - } - Assembler::cvtsi2ssq(dst, src); -} -#endif // _LP64 - void MacroAssembler::locked_cmpxchgptr(Register reg, AddressLiteral adr, Register rscratch) { assert(rscratch != noreg || always_reachable(adr), "missing"); diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.hpp b/src/hotspot/cpu/x86/macroAssembler_x86.hpp index b474944c4bead..4b30168452796 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp @@ -800,23 +800,6 @@ class MacroAssembler: public Assembler { void cmpxchgptr(Register reg, Address adr); - - // cvt instructions - void cvtss2sd(XMMRegister dst, XMMRegister src); - void cvtss2sd(XMMRegister dst, Address src); - void cvtsd2ss(XMMRegister dst, XMMRegister src); - void cvtsd2ss(XMMRegister dst, Address src); - void cvtsi2sdl(XMMRegister dst, Register src); - void cvtsi2sdl(XMMRegister dst, Address src); - void cvtsi2ssl(XMMRegister dst, Register src); - void cvtsi2ssl(XMMRegister dst, Address src); -#ifdef _LP64 - void cvtsi2sdq(XMMRegister dst, Register src); - void cvtsi2sdq(XMMRegister dst, Address src); - void cvtsi2ssq(XMMRegister dst, Register src); - void cvtsi2ssq(XMMRegister dst, Address src); -#endif - void locked_cmpxchgptr(Register reg, AddressLiteral adr, Register rscratch = noreg); void imulptr(Register dst, Register src) { LP64_ONLY(imulq(dst, src)) NOT_LP64(imull(dst, src)); } diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad index 759dd8a1d485b..80f281a1bf92d 100644 --- a/src/hotspot/cpu/x86/x86_64.ad +++ b/src/hotspot/cpu/x86/x86_64.ad @@ -10095,7 +10095,7 @@ instruct cmpD_imm(rRegI dst, regD src, immD con, rFlagsReg cr) %{ instruct convF2D_reg_reg(regD dst, regF src) %{ match(Set dst (ConvF2D src)); - effect(TEMP dst); + format %{ "cvtss2sd $dst, $src" %} ins_encode %{ __ cvtss2sd ($dst$$XMMRegister, $src$$XMMRegister); @@ -10117,7 +10117,7 @@ instruct convF2D_reg_mem(regD dst, memory src) instruct convD2F_reg_reg(regF dst, regD src) %{ match(Set dst (ConvD2F src)); - effect(TEMP dst); + format %{ "cvtsd2ss $dst, $src" %} ins_encode %{ __ cvtsd2ss ($dst$$XMMRegister, $src$$XMMRegister); diff --git a/test/micro/org/openjdk/bench/vm/compiler/x86/ComputePI.java b/test/micro/org/openjdk/bench/vm/compiler/x86/ComputePI.java deleted file mode 100644 index 7d8e479172e90..0000000000000 --- a/test/micro/org/openjdk/bench/vm/compiler/x86/ComputePI.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2023, 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 org.openjdk.bench.vm.compiler; - -import org.openjdk.jmh.annotations.Benchmark; -import org.openjdk.jmh.annotations.BenchmarkMode; -import org.openjdk.jmh.annotations.Fork; -import org.openjdk.jmh.annotations.Measurement; -import org.openjdk.jmh.annotations.Mode; -import org.openjdk.jmh.annotations.OutputTimeUnit; -import org.openjdk.jmh.annotations.Scope; -import org.openjdk.jmh.annotations.Setup; -import org.openjdk.jmh.annotations.State; -import org.openjdk.jmh.annotations.Warmup; - -import java.util.concurrent.TimeUnit; - -@State(Scope.Thread) -@BenchmarkMode(Mode.AverageTime) -@OutputTimeUnit(TimeUnit.NANOSECONDS) -@Warmup(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS) -@Measurement(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS) -@Fork(value = 3) -public class ComputePI { - - @Benchmark - public double compute_pi_int_dbl() { - double pi = 4.0; - boolean sign = false; - - for (int i = 3; i < 1000; i += 2) { - if (sign) { - pi += 4.0 / i; - } else { - pi -= 4.0 / i; - } - sign = !sign; - } - return pi; - } - - @Benchmark - public double compute_pi_int_flt() { - float pi = 4.0f; - boolean sign = false; - - for (int i = 3; i < 1000; i += 2) { - if (sign) { - pi += 4.0f / i; - } else { - pi -= 4.0f / i; - } - sign = !sign; - } - return pi; - } - - @Benchmark - public double compute_pi_long_dbl() { - double pi = 4.0; - boolean sign = false; - - for (long i = 3; i < 1000; i += 2) { - if (sign) { - pi += 4.0 / i; - } else { - pi -= 4.0 / i; - } - sign = !sign; - } - return pi; - } - - @Benchmark - public double compute_pi_long_flt() { - float pi = 4.0f; - boolean sign = false; - - for (long i = 3; i < 1000; i += 2) { - if (sign) { - pi += 4.0f / i; - } else { - pi -= 4.0f / i; - } - sign = !sign; - } - return pi; - } - - @Benchmark - public double compute_pi_flt_dbl() { - double pi = 4.0; - boolean sign = false; - - for (float i = 3.0f; i < 1000.0f; i += 2.0f) { - if (sign) { - pi += 4.0 / i; - } else { - pi -= 4.0 / i; - } - sign = !sign; - } - return pi; - } - - @Benchmark - public double compute_pi_dbl_flt() { - float pi = 4.0f; - boolean sign = false; - - for (float i = 3.0f; i < 1000.0f; i += 2.0f) { - if (sign) { - pi += 4.0f / i; - } else { - pi -= 4.0f / i; - } - sign = !sign; - } - return pi; - } -} From 631a9f60f30fe298791aa953fa573001127ff58a Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Fri, 5 Jan 2024 16:26:02 +0000 Subject: [PATCH 2/7] 8323073: ProblemList gc/g1/TestSkipRebuildRemsetPhase.java on linux-aarch64 8323075: ProblemList runtime/cds/appcds/jigsaw/modulepath/OptimizeModuleHandlingTest.java Reviewed-by: thartmann --- test/hotspot/jtreg/ProblemList.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 754cf68ba591f..f6913a0734ddc 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -93,6 +93,7 @@ gc/stress/gclocker/TestGCLockerWithParallel.java 8180622 generic-all gc/stress/gclocker/TestGCLockerWithSerial.java 8180622 generic-all gc/stress/gclocker/TestGCLockerWithShenandoah.java 8180622 generic-all gc/stress/TestStressG1Humongous.java 8286554 windows-x64 +gc/g1/TestSkipRebuildRemsetPhase.java 8323066 linux-aarch64 ############################################################################# @@ -112,6 +113,7 @@ runtime/StackGuardPages/TestStackGuardPagesNative.java 8303612 linux-all runtime/ErrorHandling/TestDwarf.java#checkDecoder 8305489 linux-all runtime/ErrorHandling/MachCodeFramesInErrorFile.java 8313315 linux-ppc64le runtime/cds/appcds/customLoader/HelloCustom_JFR.java 8241075 linux-all,windows-x64 +runtime/cds/appcds/jigsaw/modulepath/OptimizeModuleHandlingTest.java 8323032 generic-all applications/jcstress/copy.java 8229852 linux-all From 700c25f5b45e8a228d07c57dcf925e93d494af23 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Fri, 5 Jan 2024 17:04:32 +0000 Subject: [PATCH 3/7] 8322954: Shenandoah: Convert evac-update closures asserts to rich asserts Reviewed-by: wkemper, kdnilsen, ysr --- .../share/gc/shenandoah/shenandoahBarrierSet.inline.hpp | 2 +- .../share/gc/shenandoah/shenandoahBarrierSetClone.inline.hpp | 2 +- src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp | 4 +--- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp index b8da50dd6e109..bfb69c38c332c 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp @@ -357,7 +357,7 @@ void ShenandoahBarrierSet::arraycopy_work(T* src, size_t count) { if (EVAC && obj == fwd) { fwd = _heap->evacuate_object(obj, thread); } - assert(obj != fwd || _heap->cancelled_gc(), "must be forwarded"); + shenandoah_assert_forwarded_except(elem_ptr, obj, _heap->cancelled_gc()); ShenandoahHeap::atomic_update_oop(fwd, elem_ptr, o); obj = fwd; } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSetClone.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSetClone.inline.hpp index b548073be3306..13371f5e194d9 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSetClone.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSetClone.inline.hpp @@ -53,7 +53,7 @@ class ShenandoahUpdateRefsForOopClosure: public BasicOopIterateClosure { if (EVAC && obj == fwd) { fwd = _heap->evacuate_object(obj, _thread); } - assert(obj != fwd || _heap->cancelled_gc(), "must be forwarded"); + shenandoah_assert_forwarded_except(p, obj, _heap->cancelled_gc()); ShenandoahHeap::atomic_update_oop(fwd, p, o); obj = fwd; } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp index 7564af5f6b7c1..c7284fbceadbd 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahConcurrentGC.cpp @@ -705,10 +705,8 @@ void ShenandoahEvacUpdateCleanupOopStorageRootsClosure::do_oop(oop* p) { if (resolved == obj) { resolved = _heap->evacuate_object(obj, _thread); } + shenandoah_assert_not_in_cset_except(p, resolved, _heap->cancelled_gc()); ShenandoahHeap::atomic_update_oop(resolved, p, obj); - assert(_heap->cancelled_gc() || - _mark_context->is_marked(resolved) && !_heap->in_collection_set(resolved), - "Sanity"); } } } From 46965a096ce74d9375df36a3a66107e9295cc180 Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Fri, 5 Jan 2024 17:53:45 +0000 Subject: [PATCH 4/7] 8322981: Fix 2 locations in JDI that throw IOException without using the "Caused by" exception Reviewed-by: dholmes, lmesnik --- .../classes/com/sun/tools/jdi/ProcessAttachingConnector.java | 4 ++-- .../classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/jdk.jdi/share/classes/com/sun/tools/jdi/ProcessAttachingConnector.java b/src/jdk.jdi/share/classes/com/sun/tools/jdi/ProcessAttachingConnector.java index 230f3eb1cd3f8..cc5063a2fc4ec 100644 --- a/src/jdk.jdi/share/classes/com/sun/tools/jdi/ProcessAttachingConnector.java +++ b/src/jdk.jdi/share/classes/com/sun/tools/jdi/ProcessAttachingConnector.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -103,7 +103,7 @@ public VirtualMachine attach(Map args) Properties props = vm.getAgentProperties(); address = props.getProperty("sun.jdwp.listenerAddress"); } catch (Exception x) { - throw new IOException(x.getMessage()); + throw new IOException(x); } finally { if (vm != null) vm.detach(); } diff --git a/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java b/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java index 074677260d80b..c17c46237b6cb 100644 --- a/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java +++ b/src/jdk.jdi/share/classes/com/sun/tools/jdi/VirtualMachineManagerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 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 @@ -226,7 +226,7 @@ public synchronized VirtualMachine createVirtualMachine( vm = new VirtualMachineImpl(this, connection, process, ++vmSequenceNumber); } catch (VMDisconnectedException e) { - throw new IOException(e.getMessage()); + throw new IOException(e); } targets.add(vm); return vm; From 35a1b77da541e4df3c4d1bab0825ea39e653808c Mon Sep 17 00:00:00 2001 From: David Leopoldseder Date: Fri, 5 Jan 2024 19:00:18 +0000 Subject: [PATCH 5/7] 8322636: [JVMCI] HotSpotSpeculationLog can be inconsistent across a single compile Reviewed-by: dnsimon, never --- .../classes/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java index 481686b0f4eb3..57cec3ef1942a 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/HotSpotSpeculationLog.java @@ -207,11 +207,14 @@ byte[] getFlattenedSpeculations(boolean validate) { return result; } + /** + * @return {@code true} if the given speculation can be performed, i.e., it never failed so far, otherwise + * return {@code false}. Note, that this method returns consistent results for any given speculation for the + * entire lifetime of the enclosing SpeculationLog object. This means that speculations failed during a + * compilation will not be updated. + */ @Override public boolean maySpeculate(SpeculationReason reason) { - if (failedSpeculations == null) { - collectFailedSpeculations(); - } if (failedSpeculations != null && failedSpeculations.length != 0) { byte[] encoding = encode(reason); return !contains(failedSpeculations, 0, encoding); From be4614eb5e4efcea3f3ef4d18f94cfb36fd557f4 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Fri, 5 Jan 2024 22:16:52 +0000 Subject: [PATCH 6/7] 8323016: Improve reporting for bad options Reviewed-by: prappo --- .../jdk/javadoc/internal/tool/Start.java | 39 +++++++++- .../tool/resources/javadoc.properties | 11 ++- .../jdk/javadoc/tool/BadOptionsTest.java | 73 ++++++++++++++++++- 3 files changed, 118 insertions(+), 5 deletions(-) diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java index 3f06cf1ae2042..6407196a2aba8 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/Start.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -40,6 +40,7 @@ import java.util.Set; import java.util.function.Supplier; import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; @@ -457,6 +458,7 @@ private Result begin(List options, Iterable fi if (haveErrors && result.isOK()) { result = ERROR; } + log.flush(); log.printErrorWarningCounts(); log.flush(); } @@ -657,11 +659,44 @@ int consumeDocletOption(int idx, List args, boolean isToolOption) throws // check if arg is accepted by the tool before emitting error if (!isToolOption) { text = log.getText("main.invalid_flag", arg); - throw new OptionException(ERROR, this::showUsage, text); + throw new OptionException(ERROR, () -> reportBadOption(arg), text); } return m * idx; } + private void reportBadOption(String name) { + var allOptionNames = Stream.concat( + getToolOptions().getSupportedOptions().stream() + .flatMap(o -> o.getNames().stream()), + docletOptions.stream() + .flatMap(o -> o.getNames().stream())); + record Pair(String word, double similarity) { } + final double MIN_SIMILARITY = 0.7; + var suggestions = allOptionNames + .map(t -> new Pair(t, similarity(t, name))) + .sorted(Comparator.comparingDouble(Pair::similarity).reversed() /* more similar first */) + // .peek(p -> System.out.printf("%.3f, (%s ~ %s)%n", p.similarity, p.word, name)) // debug + .takeWhile(p -> Double.compare(p.similarity, MIN_SIMILARITY) >= 0) + .map(Pair::word) + .toList(); + switch (suggestions.size()) { + case 0 -> { } + case 1 -> showLinesUsingKey("main.did-you-mean", suggestions.getFirst()); + default -> showLinesUsingKey("main.did-you-mean-one-of", String.join(" ", suggestions)); + } + showLinesUsingKey("main.for-more-details-see-usage"); + } + + // a value in [0, 1] range: the closer the value is to 1, the more similar + // the strings are + private static double similarity(String a, String b) { + // Normalize the distance so that similarity between "x" and "y" is + // less than that of "ax" and "ay". Use the greater of two lengths + // as normalizer, as it's an upper bound for the distance. + return 1.0 - ((double) StringUtils.DamerauLevenshteinDistance.of(a, b)) + / Math.max(a.length(), b.length()); + } + private static Set getSupportedOptionsOf(Doclet doclet) { Set options = doclet.getSupportedOptions(); return options == null ? Set.of() : options; diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc.properties index e4aacca212d18..ef9425a02be4b 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1997, 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 @@ -34,6 +34,15 @@ main.usage=Usage:\n\ \ javadoc [options] [packagenames] [sourcefiles] [@files]\n\ where options include: +main.did-you-mean=\ + Did you mean: {0} + +main.did-you-mean-one-of=\ + Did you mean one of: {0} + +main.for-more-details-see-usage=\ + For more details on available options, use --help or --help-extra + main.opt.at.arg=\ main.opt.at.desc=\ diff --git a/test/langtools/jdk/javadoc/tool/BadOptionsTest.java b/test/langtools/jdk/javadoc/tool/BadOptionsTest.java index e0887ed564653..568b6de90556a 100644 --- a/test/langtools/jdk/javadoc/tool/BadOptionsTest.java +++ b/test/langtools/jdk/javadoc/tool/BadOptionsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2021, 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 @@ -23,7 +23,7 @@ /* * @test - * @bug 8169676 8175055 + * @bug 8169676 8175055 8323016 * @summary boolean result of Option.process is often ignored * @modules jdk.compiler/com.sun.tools.javac.api * @modules jdk.compiler/com.sun.tools.javac.main @@ -151,6 +151,75 @@ public void testSourcePathAndModuleSourceConflict() throws IOException { "1 error"); } + @Test + public void testOptionNotFound_NoSuggestions() { + var result = new JavadocTask(tb, Task.Mode.CMDLINE) + .options("--not-a-path") + .run(Task.Expect.FAIL) + .writeAll(); + checkFound(String.join("\n", result.getOutputLines(Task.OutputKind.DIRECT)), + """ + error: invalid flag: --not-a-path + For more details on available options, use --help or --help-extra""" + ); + } + + @Test + public void testOptionNotFound_OneSuggestion() { + var result = new JavadocTask(tb, Task.Mode.CMDLINE) + .options("--middle-path") + .run(Task.Expect.FAIL) + .writeAll(); + checkFound(String.join("\n", result.getOutputLines(Task.OutputKind.DIRECT)), + """ + error: invalid flag: --middle-path + Did you mean: --module-path + For more details on available options, use --help or --help-extra""" + ); + } + + @Test + public void testOptionNotFound_TwoSuggestions() { + var result = new JavadocTask(tb, Task.Mode.CMDLINE) + .options("--sourcepath") + .run(Task.Expect.FAIL) + .writeAll(); + checkFound(String.join("\n", result.getOutputLines(Task.OutputKind.DIRECT)), + """ + error: invalid flag: --sourcepath + Did you mean one of: --source-path -sourcepath + For more details on available options, use --help or --help-extra""" + ); + } + + @Test + public void testOptionNotFound_ThreeSuggestions() { + var result = new JavadocTask(tb, Task.Mode.CMDLINE) + .options("--classpath") + .run(Task.Expect.FAIL) + .writeAll(); + checkFound(String.join("\n", result.getOutputLines(Task.OutputKind.DIRECT)), + """ + error: invalid flag: --classpath + Did you mean one of: --class-path -classpath -bootclasspath + For more details on available options, use --help or --help-extra""" + ); + } + + @Test + public void testOptionNotFound_DocletOption() { + var result = new JavadocTask(tb, Task.Mode.CMDLINE) + .options("-tiglet") + .run(Task.Expect.FAIL) + .writeAll(); + checkFound(String.join("\n", result.getOutputLines(Task.OutputKind.DIRECT)), + """ + error: invalid flag: -tiglet + Did you mean: -taglet + For more details on available options, use --help or --help-extra""" + ); + } + private void checkFound(String log, String... expect) { for (String e : expect) { if (!log.contains(e)) { From ace010b38a83e0c9b43aeeb6bc5c92d0886dc53f Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Sat, 6 Jan 2024 08:52:27 +0000 Subject: [PATCH 7/7] 8319757: java/nio/channels/DatagramChannel/InterruptibleOrNot.java failed: wrong exception thrown Reviewed-by: jpai, bpb --- .../DatagramChannel/InterruptibleOrNot.java | 238 ++++++++++-------- 1 file changed, 132 insertions(+), 106 deletions(-) diff --git a/test/jdk/java/nio/channels/DatagramChannel/InterruptibleOrNot.java b/test/jdk/java/nio/channels/DatagramChannel/InterruptibleOrNot.java index 7d369d7ddd99f..794ede84a924a 100644 --- a/test/jdk/java/nio/channels/DatagramChannel/InterruptibleOrNot.java +++ b/test/jdk/java/nio/channels/DatagramChannel/InterruptibleOrNot.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 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 @@ -25,7 +25,7 @@ * @test * @bug 8236246 * @modules java.base/sun.nio.ch - * @run testng InterruptibleOrNot + * @run junit InterruptibleOrNot * @summary Test SelectorProviderImpl.openDatagramChannel(boolean) to create * DatagramChannel objects that optionally support interrupt */ @@ -40,152 +40,178 @@ import java.nio.channels.ClosedByInterruptException; import java.nio.channels.DatagramChannel; import java.time.Duration; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; +import java.util.Arrays; import sun.nio.ch.DefaultSelectorProvider; -import org.testng.annotations.Test; -import static org.testng.Assert.*; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.function.Executable; +import static org.junit.jupiter.api.Assertions.*; -@Test public class InterruptibleOrNot { + // DatagramChannel implementation class + private static String dcImplClassName; - public void testInterruptBeforeInterruptibleReceive() throws Exception { - testInterruptBeforeReceive(true); - } - - public void testInterruptDuringInterruptibleReceive() throws Exception { - testInterruptDuringReceive(true); - } - - public void testInterruptBeforeUninterruptibleReceive() throws Exception { - testInterruptBeforeReceive(false); - } - - public void testInterruptDuringUninterruptibleReceive() throws Exception { - testInterruptDuringReceive(false); - } - - public void testInterruptBeforeInterruptibleSend() throws Exception { - testInterruptBeforeSend(true); + @BeforeAll + static void setup() throws Exception { + try (DatagramChannel dc = boundDatagramChannel(true)) { + dcImplClassName = dc.getClass().getName(); + } } - public void testInterruptBeforeUninterruptibleSend() throws Exception { - testInterruptBeforeSend(false); + /** + * Call DatagramChannel.receive with the interrupt status set, the DatagramChannel + * is interruptible. + */ + @Test + public void testInterruptBeforeInterruptibleReceive() throws Exception { + try (DatagramChannel dc = boundDatagramChannel(true)) { + ByteBuffer buf = ByteBuffer.allocate(100); + Thread.currentThread().interrupt(); + assertThrows(ClosedByInterruptException.class, () -> dc.receive(buf)); + assertFalse(dc.isOpen()); + } finally { + Thread.interrupted(); // clear interrupt status + } } /** - * Test invoking DatagramChannel receive with interrupt status set + * Test interrupting a thread blocked in DatagramChannel.receive, the DatagramChannel + * is interruptible. */ - static void testInterruptBeforeReceive(boolean interruptible) - throws Exception - { - try (DatagramChannel dc = openDatagramChannel(interruptible)) { - dc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); - Future timeout = scheduleClose(dc, Duration.ofSeconds(2)); - try { - ByteBuffer buf = ByteBuffer.allocate(100); - Thread.currentThread().interrupt(); - assertThrows(expectedException(interruptible), () -> dc.receive(buf)); - } finally { - timeout.cancel(false); - } + @Test + public void testInterruptDuringInterruptibleReceive() throws Exception { + try (DatagramChannel dc = boundDatagramChannel(true)) { + ByteBuffer buf = ByteBuffer.allocate(100); + Thread thread = Thread.currentThread(); + onReceive(thread::interrupt); + assertThrows(ClosedByInterruptException.class, () -> dc.receive(buf)); + assertFalse(dc.isOpen()); } finally { - Thread.interrupted(); // clear interrupt + Thread.interrupted(); // clear interrupt status } } /** - * Test Thread.interrupt when target thread is blocked in DatagramChannel receive + * Call DatagramChannel.receive with the interrupt status set, the DatagramChannel + * is not interruptible. */ - static void testInterruptDuringReceive(boolean interruptible) - throws Exception - { - try (DatagramChannel dc = openDatagramChannel(interruptible)) { - dc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); - Future timerTask = scheduleClose(dc, Duration.ofSeconds(5)); - Future interruptTask = scheduleInterrupt(Thread.currentThread(), Duration.ofSeconds(1)); - try { - ByteBuffer buf = ByteBuffer.allocate(100); - assertThrows(expectedException(interruptible), () -> dc.receive(buf)); - } finally { - timerTask.cancel(false); - interruptTask.cancel(false); - } + @Test + public void testInterruptBeforeUninterruptibleReceive() throws Exception { + try (DatagramChannel dc = boundDatagramChannel(false)) { + ByteBuffer buf = ByteBuffer.allocate(100); + onReceive(() -> { + // close the channel after a delay to ensure receive wakes up + Thread.sleep(1000); + dc.close(); + }); + Thread.currentThread().interrupt(); + assertThrows(AsynchronousCloseException.class, () -> dc.receive(buf)); + assertFalse(dc.isOpen()); } finally { - Thread.interrupted(); // clear interrupt + Thread.interrupted(); // clear interrupt status } } /** - * Test invoking DatagramChannel send with interrupt status set + * Test interrupting a thread blocked in DatagramChannel.receive, the DatagramChannel + * is not interruptible. */ - static void testInterruptBeforeSend(boolean interruptible) - throws Exception - { - try (DatagramChannel dc = openDatagramChannel(interruptible)) { - dc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); - Future timeout = scheduleClose(dc, Duration.ofSeconds(2)); - try { - ByteBuffer buf = ByteBuffer.allocate(100); - SocketAddress target = dc.getLocalAddress(); - Thread.currentThread().interrupt(); - if (interruptible) { - assertThrows(ClosedByInterruptException.class, () -> dc.send(buf, target)); - } else { - int n = dc.send(buf, target); - assertTrue(n == 100); - } - } finally { - timeout.cancel(false); - } + @Test + public void testInterruptDuringUninterruptibleReceive() throws Exception { + try (DatagramChannel dc = boundDatagramChannel(true)) { + ByteBuffer buf = ByteBuffer.allocate(100); + + Thread thread = Thread.currentThread(); + onReceive(() -> { + // interrupt should not cause the receive to wakeup + thread.interrupt(); + + // close the channel after a delay to ensure receive wakes up + Thread.sleep(1000); + dc.close(); + }); + assertThrows(AsynchronousCloseException.class, () -> dc.receive(buf)); + assertFalse(dc.isOpen()); } finally { - Thread.interrupted(); // clear interrupt + Thread.interrupted(); // clear interrupt status } } /** - * Creates a DatagramChannel that is interruptible or not. + * Call DatagramChannel.send with the interrupt status set, the DatagramChannel + * is interruptible. */ - static DatagramChannel openDatagramChannel(boolean interruptible) throws IOException { - if (interruptible) { - return DatagramChannel.open(); - } else { - return DefaultSelectorProvider.get().openUninterruptibleDatagramChannel(); + @Test + public void testInterruptBeforeInterruptibleSend() throws Exception { + try (DatagramChannel dc = boundDatagramChannel(true)) { + ByteBuffer buf = ByteBuffer.allocate(100); + SocketAddress target = dc.getLocalAddress(); + Thread.currentThread().interrupt(); + assertThrows(ClosedByInterruptException.class, () -> dc.send(buf, target)); + assertFalse(dc.isOpen()); + } finally { + Thread.interrupted(); // clear interrupt } } /** - * Expect ClosedByInterruptException if interruptible. + * Call DatagramChannel.send with the interrupt status set, the DatagramChannel + * is not interruptible. */ - static Class expectedException(boolean expectInterrupt) { - if (expectInterrupt) { - return ClosedByInterruptException.class; - } else { - return AsynchronousCloseException.class; + @Test + public void testInterruptBeforeUninterruptibleSend() throws Exception { + try (DatagramChannel dc = boundDatagramChannel(false)) { + ByteBuffer buf = ByteBuffer.allocate(100); + SocketAddress target = dc.getLocalAddress(); + Thread.currentThread().interrupt(); + int n = dc.send(buf, target); + assertEquals(100, n); + assertTrue(dc.isOpen()); + } finally { + Thread.interrupted(); // clear interrupt status } } /** - * Schedule the given object to be closed. + * Creates a DatagramChannel that is interruptible or not, and bound to the loopback + * address. */ - static Future scheduleClose(Closeable c, Duration timeout) { - long nanos = TimeUnit.NANOSECONDS.convert(timeout); - return STPE.schedule(() -> { - c.close(); - return null; - }, nanos, TimeUnit.NANOSECONDS); + static DatagramChannel boundDatagramChannel(boolean interruptible) throws IOException { + DatagramChannel dc; + if (interruptible) { + dc = DatagramChannel.open(); + } else { + dc = DefaultSelectorProvider.get().openUninterruptibleDatagramChannel(); + } + try { + dc.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); + } catch (IOException ioe) { + dc.close(); + throw ioe; + } + return dc; } /** - * Schedule the given thread to be interrupted. + * Runs the given action when the current thread is sampled in DatagramChannel.receive. */ - static Future scheduleInterrupt(Thread t, Duration timeout) { - long nanos = TimeUnit.NANOSECONDS.convert(timeout); - return STPE.schedule(t::interrupt, nanos, TimeUnit.NANOSECONDS); + static void onReceive(Executable action) { + Thread target = Thread.currentThread(); + Thread.ofPlatform().daemon().start(() -> { + try { + boolean found = false; + while (!found) { + Thread.sleep(20); + StackTraceElement[] stack = target.getStackTrace(); + found = Arrays.stream(stack) + .anyMatch(e -> dcImplClassName.equals(e.getClassName()) + && "receive".equals(e.getMethodName())); + } + action.execute(); + } catch (Throwable ex) { + ex.printStackTrace(); + } + }); } - - static final ScheduledExecutorService STPE = Executors.newScheduledThreadPool(0); }